CustomPanel.cs
7.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace flowchart
{
// 각종 선택 상황을 열거형으로 정의
public enum State
{
NONE, RECTANGLE, RHOMBUS, PARALLELOGRAM, LINKLINE, MOVE
}
// flowchart를 그리는 판넬에 필요한 기능을 삽입. (Panel 객체를 상속해서 사용했음)
// 마우스 클릭을 놓으면 어떤 도형 또는 선을 선택했는지 판단해서, 해당 자료구조를 생성하고, 페인트 함수를 통해 그린다.
class CustomPanel : Panel
{
public static Control _parentControl = null; // 텍스트박스에서 부모로 정의하기 위한 변수
public CustomPanel() // 생성자
{
_parentControl = this;
}
private State _selectState = State.NONE; // 열거형을 사용하기 위한 변수
private List<FigBase> _shapes = new List<FigBase>(); // 도형을 저장한 리스트 자료구조
private List<FigLinkline> _linkLines = new List<FigLinkline>(); // 링크 선을 저장한 리스트 자료구조
private FigBase _linkStartShape = null; // 처음 선택한 도형을 저장하는 변수
private FigBase _movingShape = null; // 도형을 움직이겠다고 선택된 경우 해당 도형을 저장하는 변수
// 외부 클래스에서 호출되는 변수(열거형 값) 정의
public State SelectState { get { return _selectState; } set { _selectState = value; } }
// 마우스를 판넬에서 움질일때 호출되는 이벤트 함수
protected override void OnMouseMove(MouseEventArgs e)
{
// System.Diagnostics.Trace.WriteLine("debug >>>" + _state); // 디버깅
// 마우스 버튼을 누르지 않은 상태일 경우
if (e.Button == MouseButtons.None)
{
// 그려진 도형위에 마우스가 오면 마우스 모양을 변경
FigBase shape = FindShapeByLocation(e.Location);
if (shape != null)
Cursor = Cursors.SizeAll; // 도형 안에 마우스가 있을 경우 마우스 모양 변경
else
Cursor = Cursors.Default; // 도형 밖에 마우스 포인터가 있을 경우 마우스 모양 변경
// 도형 안에 마우스가 있고, 링크 라인을 그리겠다고 선택
if (shape != null && _selectState == State.LINKLINE)
Cursor = Cursors.Cross;
}
// 마우스를 클릭한 상태에서 링크 라인을 그리지 않겠다고 선택된 경우
else if (e.Button == MouseButtons.Left && _selectState != State.LINKLINE)
{
FigBase shape = FindShapeByLocation(e.Location); // 마우스가 어떤 도형안에 있는지 검색
if (shape != null)
{
_selectState = State.MOVE; // 움직이는 상태로 바꿈
_movingShape = shape; // 해당 도형을 레퍼런스
}
}
// 마우스를 클릭한 상태에서 링크 라인을 그리겠다고 선택한 경우
else if (e.Button == MouseButtons.Left && _selectState == State.LINKLINE)
{
// 처음 도형을 선택한것만 저장하기 위함. (다른 영역의 도형으로 넘어가도 실행안함)
if (_linkStartShape == null)
{
_linkStartShape = FindShapeByLocation(e.Location); // 마우스가 어떤 도형안에 있는지 검색
if (_linkStartShape != null)
{
_selectState = State.LINKLINE;
}
}
}
base.OnMouseMove(e);
}
// 실제 그릴 도형정보를 리스트 자료구조에 삽입하고, OnPaint() 함수를 호출
protected override void OnMouseUp(MouseEventArgs e)
{
if (_selectState == State.RECTANGLE) // 사각형 그리기 선택
{
// 사각형에 대한 정보를 자료구조에 삽입한다.
FigRectangle rectangle = new FigRectangle(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(rectangle);
}
else if (_selectState == State.RHOMBUS) // 마름모 그리기 선택
{
FigRhombus rhombus = new FigRhombus(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(rhombus);
}
else if (_selectState == State.PARALLELOGRAM) // 평행사변형 그리기 선택
{
FigParallelogram parallelogram = new FigParallelogram(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(parallelogram);
}
else if (_selectState == State.MOVE) // 도형을 움직이는 상태로 선택한 경우
{
if (_movingShape != null)
{
_movingShape.Location = e.Location; // 자료구조에서 찾은 도형의 위치값을 옮길위치로 수정
}
}
else if (_selectState == State.LINKLINE) // 선을 그리기로 선택한 경우
{
if (_linkStartShape != null)
{
FigBase shape = FindShapeByLocation(e.Location); // 마우스를 클릭을 놓은 위치에 도형이 있는지 확인
if (shape == null)
{
MessageBox.Show(this, "해당 위치에 연결대상 도형이 없습니다.", "알림",
MessageBoxButtons.OK, MessageBoxIcon.Information);
_linkStartShape = null; // mouse move 이벤트 함수에서 한번은 실행하게 처리
}
else
{
FigLinkline linkLine = new FigLinkline(_linkStartShape, shape); // 처음 선택한 도형과 현재 도형에 링크 라인을 연결 함
_linkLines.Add(linkLine);
_linkStartShape = null; // mouse move 이벤트 함수에서 한번은 실행하게 처리
}
}
}
_selectState = State.NONE;
this.Refresh(); // 다시 그리기 요청: OnPaint()
base.OnMouseUp(e);
}
// 도형 안에서 마우스를 더블클릭하면 텍스트 에디터를 삽입한다.
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
FigBase shape = FindShapeByLocation(e.Location);
if (shape != null)
{
shape.EnterEditMode(); // FigBase에 함수 있음
}
base.OnMouseDoubleClick(e);
}
// 실제 그리는 OnPaint를 통해 내가 작성한 Draw함수를 호출한다.
protected override void OnPaint(PaintEventArgs e)
{
// 자료구조에 저장된 도형을 다시 그림
foreach (FigBase s in _shapes)
{
s.Draw(e.Graphics);
}
// 자료구조에 저장된 링크라인을 다시 그림
foreach (FigLinkline l in _linkLines)
{
l.Draw(e.Graphics);
}
base.OnPaint(e);
}
// 현재 위치에 해당하는 도형을 자료구조에서 찾아서 레퍼런스 함
private FigBase FindShapeByLocation(Point location)
{
foreach (FigBase s in _shapes)
{
if (s.PointInRegion(location))
{
return s;
}
}
return null;
}
}
}