Public Class GraphicsPanel
    Inherits System.Windows.Forms.UserControl

#Region " Windows フォーム デザイナで生成されたコード "

    Public Sub New()
        MyBase.New()

        ' この呼び出しは Windows フォーム デザイナで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後に初期化を追加します。

    End Sub

    'UserControl はコンポーネント一覧を消去するために dispose をオーバーライドします。
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    ' Windows フォーム デザイナで必要です。
    Private components As System.ComponentModel.IContainer

    ' メモ : 以下のプロシージャは、Windows フォーム デザイナで必要です。
    'Windows フォーム デザイナを使って変更してください。  
    ' コード エディタを使って変更しないでください。
    Friend WithEvents VScrollBar1 As System.Windows.Forms.VScrollBar
    Friend WithEvents HScrollBar1 As System.Windows.Forms.HScrollBar
    Friend WithEvents DrawPanel As DoubleBufferedPanel
    Friend WithEvents OpenFileDialog1 As System.Windows.Forms.OpenFileDialog
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.VScrollBar1 = New System.Windows.Forms.VScrollBar
        Me.HScrollBar1 = New System.Windows.Forms.HScrollBar
        Me.DrawPanel = New DoubleBufferedPanel
        Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog
        Me.SuspendLayout()
        '
        'VScrollBar1
        '
        Me.VScrollBar1.Dock = System.Windows.Forms.DockStyle.Right
        Me.VScrollBar1.Location = New System.Drawing.Point(511, 0)
        Me.VScrollBar1.Maximum = 297
        Me.VScrollBar1.Name = "VScrollBar1"
        Me.VScrollBar1.Size = New System.Drawing.Size(17, 480)
        Me.VScrollBar1.SmallChange = 10
        Me.VScrollBar1.TabIndex = 0
        '
        'HScrollBar1
        '
        Me.HScrollBar1.Dock = System.Windows.Forms.DockStyle.Bottom
        Me.HScrollBar1.Location = New System.Drawing.Point(0, 463)
        Me.HScrollBar1.Maximum = 210
        Me.HScrollBar1.Name = "HScrollBar1"
        Me.HScrollBar1.Size = New System.Drawing.Size(511, 17)
        Me.HScrollBar1.SmallChange = 10
        Me.HScrollBar1.TabIndex = 1
        '
        'DrawPanel
        '
        Me.DrawPanel.BackColor = System.Drawing.SystemColors.Window
        Me.DrawPanel.Dock = System.Windows.Forms.DockStyle.Fill
        Me.DrawPanel.Location = New System.Drawing.Point(0, 0)
        Me.DrawPanel.Name = "DrawPanel"
        Me.DrawPanel.Size = New System.Drawing.Size(511, 463)
        Me.DrawPanel.TabIndex = 2
        '
        'OpenFileDialog1
        '
        Me.OpenFileDialog1.Filter = "画像ファイル|*.bmp;*.jpg;*.jpeg;*.gif;*.png;*.wmf|すべてのファイル|*.*"
        Me.OpenFileDialog1.Title = "画像の選択"
        '
        'GraphicsPanel
        '
        Me.Controls.Add(Me.DrawPanel)
        Me.Controls.Add(Me.HScrollBar1)
        Me.Controls.Add(Me.VScrollBar1)
        Me.Name = "GraphicsPanel"
        Me.Size = New System.Drawing.Size(528, 480)
        Me.ResumeLayout(False)

    End Sub

#End Region

    Event ResetTool()
    Event SelectedObjectChanged(ByVal NewObject As GraphicBase)

    Dim _tool As SelectedTool = _Const.SelectedTool.None
    Dim scrolloffset As PointF = New PointF(0, 0)
    Dim gobjects As GraphicsObjects
    Dim _linecolor, _fillcolor As Color

    Public Property LineColor() As Color
        Get
            Return _linecolor
        End Get
        Set(ByVal Value As Color)
            _linecolor = Value
            If Not IsNothing(hitObject) Then
                hitObject.LineColor = Value
                DrawPanel.Invalidate()
            End If
        End Set
    End Property

    Public Property FillColor() As Color
        Get
            Return _fillcolor
        End Get
        Set(ByVal Value As Color)
            _fillcolor = Value
            If Not IsNothing(hitObject) Then
                hitObject.FillColor = Value
                DrawPanel.Invalidate()
            End If
        End Set
    End Property


    Public WriteOnly Property Objects() As GraphicsObjects
        Set(ByVal Value As GraphicsObjects)
            gobjects = Value
            HScrollBar1.Value = 0
            VScrollBar1.Value = 0
            scrolloffset = New PointF(0, 0)
            DrawPanel.Invalidate()
        End Set
    End Property

    Public Property Tool() As SelectedTool
        Get
            Return _tool
        End Get
        Set(ByVal Value As SelectedTool)
            _tool = Value
            If _tool = _Const.SelectedTool.None Then
                DrawPanel.Cursor = Cursors.Default
            Else
                DrawPanel.Cursor = Cursors.Cross
            End If
        End Set
    End Property

    Dim isDrag As Boolean = False
    Dim isMove As Boolean = False
    Dim startPos, endPos, originalPos As PointF
    Dim drawingObject As GraphicBase
    Dim hitObject As GraphicBase

    Private Function pix2mm(ByVal dot As Point) As PointF
        ' ピクセル位置をミリメートル位置に換算
        Dim g As Graphics = DrawPanel.CreateGraphics()
        Dim result(0) As PointF
        ' ミリメートルに
        g.PageUnit = GraphicsUnit.Millimeter
        ' オフセット分だけ移動
        g.TranslateTransform(-scrolloffset.X, -scrolloffset.Y)

        result(0) = New PointF(dot.X, dot.Y)
        g.TransformPoints(Drawing2D.CoordinateSpace.Page, Drawing2D.CoordinateSpace.Device, result)

        g.Dispose()
        Return result(0)
    End Function

    Private Sub CancelDrawing()
        ' 描画を終了させる
        If Not IsNothing(drawingObject) Then
            drawingObject.Dispose()
        End If
        drawingObject = Nothing
        DrawPanel.Invalidate()

        ' 描画が終わったことを告げる
        RaiseEvent ResetTool()
    End Sub

    Private Sub GraphicsPanel_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

    End Sub

    Private Sub DrawPanel_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DrawPanel.MouseDown
        ' マウスボタンが押されたとき
        If e.Button <> MouseButtons.Left Then
            ' 左ボタンでないなら戻る
            Exit Sub
        End If

        ' 現在の座標を保存
        startPos = pix2mm(New Point(e.X, e.Y))

        ' 選択されているツールに応じて処理を決める
        Select Case Tool
            Case _Const.SelectedTool.None
                ' 選択ツール
                ' ヒットチェック
                Dim oldHitObject As GraphicBase = hitObject
                hitObject = gobjects.HitObject(startPos)
                If Not IsNothing(hitObject) Then
                    ' 何かヒットした
                    isMove = True
                    originalPos = hitObject.Position
                End If
                If Not (oldHitObject Is hitObject) Then
                    ' 選択されているオブジェクトが変わった
                    RaiseEvent SelectedObjectChanged(hitObject)
                End If
            Case _Const.SelectedTool.Line
                ' 直線ツール
                drawingObject = New Line
                drawingObject.Position = startPos
                drawingObject.LineColor = LineColor
            Case _Const.SelectedTool.Box
                ' 四角形ツール
                drawingObject = New Box
                drawingObject.Position = startPos
                drawingObject.LineColor = LineColor
                drawingObject.FillColor = FillColor
            Case _Const.SelectedTool.Circle
                ' 円形ツール
                drawingObject = New Circle
                drawingObject.Position = startPos
                drawingObject.LineColor = LineColor
                drawingObject.FillColor = FillColor
            Case _Const.SelectedTool.Text
                ' テキストツール
                drawingObject = New TextObject
                drawingObject.Position = startPos
                drawingObject.FillColor = FillColor
            Case _Const.SelectedTool.Bitmap
                ' ビットマップツール
                drawingObject = New BitmapObject
                drawingObject.Position = startPos
        End Select

        ' ドラッグ中だとみなす
        isDrag = True
        ' 再描画
        DrawPanel.Invalidate()
    End Sub

    Private Sub DrawPanel_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DrawPanel.MouseMove
        ' マウスが動いているとき
        If Not isDrag Then
            ' ドラッグ中でないなら何もしない
            Exit Sub
        End If
        ' ドラッグ中のとき
        Debug.WriteLine("MouseMove")
        If Not IsNothing(drawingObject) Then
            ' 作成した図形の幅と高さを調整
            Dim nowPos As PointF
            nowPos = pix2mm(New Point(e.X, e.Y))
            drawingObject.Size = New SizeF(nowPos.X - startPos.X, nowPos.Y - startPos.Y)
            Debug.WriteLine("StartX=" & startPos.ToString)
            Debug.WriteLine("EndX=" & nowPos.ToString)
            ' 再描画
            DrawPanel.Invalidate()
        End If
        If Not IsNothing(hitObject) And isMove Then
            ' 図形を移動
            Dim nowPos As PointF
            nowPos = pix2mm(New Point(e.X, e.Y))
            hitObject.Position = New PointF(originalPos.X + nowPos.X - startPos.X, originalPos.Y + nowPos.Y - startPos.Y)
            ' 再描画
            DrawPanel.Invalidate()
        End If
    End Sub

    Private Sub DrawPanel_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DrawPanel.MouseUp
        ' マウスのボタンが離されたとき
        If Not isDrag Then
            ' ドラッグ中でないなら何もしない
            Exit Sub
        End If

        If Not IsNothing(drawingObject) Then
            isDrag = False

            ' テキストと画像の処理
            If Tool = _Const.SelectedTool.Text Then
                ' テキスト
                TextForm1.FontText = ""
                If TextForm1.ShowDialog() <> DialogResult.OK Then
                    ' 作成取り消し
                    CancelDrawing()
                    Exit Sub
                End If
                Dim obj As TextObject = DirectCast(drawingObject, TextObject)
                obj.FontName = TextForm1.FontName
                obj.FontPt = TextForm1.FontPt
                obj.FontText = TextForm1.FontText
            End If

            If Tool = _Const.SelectedTool.Bitmap Then
                ' ビットマップ
                If OpenFileDialog1.ShowDialog() <> DialogResult.OK Then
                    ' 作成取り消し
                    CancelDrawing()
                    Exit Sub
                End If
                Try
                    Dim bmp As Image = Image.FromFile(OpenFileDialog1.FileName)
                    Dim obj As BitmapObject = DirectCast(drawingObject, BitmapObject)
                    obj.Image = bmp
                Catch ex As Exception
                    MsgBox("画像ファイルが読めませんでした")
                    CancelDrawing()
                    Exit Sub
                End Try

            End If

            ' オブジェクトとして登録
            gobjects.AddObject(drawingObject)

            ' オブジェクトをクリア（そのまま登録するからDIsposeはしない）
            drawingObject = Nothing
            Tool = _Const.SelectedTool.None
            ' 描画が終わったことを告げる
            RaiseEvent ResetTool()
        End If
        isMove = False
        ' 再描画
        DrawPanel.Invalidate()
    End Sub

    Private Sub DrawPanel_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles DrawPanel.Paint
        ' 描画する
        ' 単位をミリメートルにする
        Dim g As Graphics = e.Graphics

        ' ミリメートルに
        g.PageUnit = GraphicsUnit.Millimeter
        ' オフセット分だけ移動
        g.TranslateTransform(-scrolloffset.X, -scrolloffset.Y)


        ' オブジェクトを描画
        If Not IsNothing(gobjects) Then
            gobjects.Draw(g)
        End If

        ' 現在作成中のオブジェクトのプレビュー
        If Not IsNothing(drawingObject) Then
            Debug.WriteLine("Draw")
            drawingObject.Draw(g, True)
        End If

        ' 選択中画面
        If Not IsNothing(hitObject) Then
            hitObject.DrawOutline(g)
        End If

    End Sub

    Public Function isSelected() As Boolean
        Return Not IsNothing(hitObject)
    End Function

    Public Sub Delete()
        ' 削除
        If Not IsNothing(hitObject) Then
            gobjects.DeleteObject(hitObject)
            hitObject = Nothing
            DrawPanel.Invalidate()
        End If
    End Sub

    Public Sub MovePrevious()
        ' 前面に移動
        If Not IsNothing(hitObject) Then
            gobjects.PreviousObject(hitObject)
            DrawPanel.Invalidate()
        End If
    End Sub

    Public Sub MoveBehind()
        ' 背面に移動
        If Not IsNothing(hitObject) Then
            gobjects.BehindObject(hitObject)
            DrawPanel.Invalidate()
        End If
    End Sub

    Dim TextForm1 As New TextForm

    Private Sub GraphicsPanel_FontChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.FontChanged
        TextForm1.InitFontList()
    End Sub

    Private Sub HScrollBar1_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles HScrollBar1.ValueChanged
        scrolloffset.X = DirectCast(sender, HScrollBar).Value
        DrawPanel.Invalidate()
    End Sub

    Private Sub VScrollBar1_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles VScrollBar1.ValueChanged
        scrolloffset.Y = DirectCast(sender, VScrollBar).Value
        DrawPanel.Invalidate()
    End Sub

    Private Sub DrawPanel_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles DrawPanel.DoubleClick
        ' ダブルクリックされたとき
        If TypeOf hitObject Is TextObject Then
            ' テキストならテキスト修正
            Dim obj As TextObject = DirectCast(hitObject, TextObject)
            TextForm1.FontName = obj.FontName
            TextForm1.FontPt = obj.FontPt
            TextForm1.FontText = obj.FontText
            If TextForm1.ShowDialog() = DialogResult.OK Then
                obj.FontName = TextForm1.FontName
                obj.FontPt = TextForm1.FontPt
                obj.FontText = TextForm1.FontText
            End If
        End If
    End Sub

    Private Sub VScrollBar1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles VScrollBar1.Scroll

    End Sub

    Private Sub GraphicsPanel_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
    End Sub
End Class
