CustomPanel.cs
7.27 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
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
{
// flowchart를 그리는 판넬에 필요한 기능을 삽입. (Panel 객체를 상속해서 사용했음)
// 마우스 클릭을 놓으면 어떤 도형 또는 선을 선택했는지 판단해서, 해당 자료구조를 생성하고, 페인트 함수를 통해 그린다.
class CustomPanel : Panel
{
private String _state; // NONE, DRAW, MOVE
private String _figName; // NONE, RECTANGLE, RHOMBUS, LINKLINE, ETC
private List<FigBase> _shapes = new List<FigBase>(); // 도형을 저장한 리스트 자료구조
private List<FigLinkline> _linkLines = new List<FigLinkline>(); // 링크 선을 저장한 리스트 자료구조
private FigBase _linkStartShape = null; // 처음 선택한 도형을 저장하는 변수
private FigBase _movingShape = null; // 도형을 움직이겠다고 선택된 경우 해당 도형을 저장하는 변수
// private 변수를 클래스 밖에서 읽고 쓰게 하는 함수
public string FigName { get { return _figName; } set { _figName = value; } }
public String State { get { return _state; } set { _state = 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 && _figName == "LINKLINE") // 링크 라인을 그리겠다고 선택하고, 도형 안에 마우스가 있을 경우
Cursor = Cursors.Cross;
}
// 마우스를 클릭한 상태에서 링크 라인을 그리지 않겠다고 선택된 경우
else if (e.Button == MouseButtons.Left && _figName != "LINKLINE")
{
FigBase shape = FindShapeByLocation(e.Location);
if (shape != null)
{
_state = "MOVE"; // 움직이는 상태로 바꿈
_movingShape = shape; // 해당 도형을 레퍼런스
}
}
// 마우스를 클릭한 상태에서 링크 라인을 그리겠다고 선택한 경우
else if (e.Button == MouseButtons.Left && _figName == "LINKLINE")
{
if (_linkStartShape == null) // 처음 도형을 선택한것만 저장하기 위함. (다른 영역의 도형으로 넘어가도 실행안함)
{
_linkStartShape = FindShapeByLocation(e.Location);
if (_linkStartShape != null)
{
_state = "MOVE";
}
}
}
base.OnMouseMove(e);
}
// 실제 도형을 그리거나 이동하는 함수, 최종 OnPaint() 함수가 호출되어 실행됨
protected override void OnMouseUp(MouseEventArgs e)
{
//System.Diagnostics.Trace.WriteLine("debug >>>" + _state);
// 그리기 상태
if (_state == "DRAW")
{
if (_figName == "RECTANGLE")
{
// 사각형에 대한 정보를 자료구조에 삽입한다.
FigRectangle rectangle = new FigRectangle(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(rectangle);
}
else if (_figName == "RHOMBUS")
{
FigRhombus rhombus = new FigRhombus(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(rhombus);
}
else if (_figName == "PARALLELOGRAM")
{
FigParallelogram parallelogram = new FigParallelogram(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(parallelogram);
}
}
// 움직이는 상태이고 링크 라인을 그리지 않는 경우 (단순 도형 이동)
else if (_state == "MOVE" && _figName != "LINKLINE")
{
if (_movingShape != null)
{
_movingShape.Location = e.Location; // 찾은 도형의 위치값을 옮길위치로 수정
}
}
// 움직이는 상태이고 링크 라인을 그리는 경우 (링크 라인을 긋는 경우)
else if (_state == "MOVE" && _figName == "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 이벤트 함수에서 한번은 실행하게 처리
}
}
}
_state = "NONE";
this.Refresh(); // 다시 그리기 요청: OnPaint()
base.OnMouseUp(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;
}
}
}