1 | using System;
|
---|
2 | using System.Drawing;
|
---|
3 | using System.Drawing.Drawing2D;
|
---|
4 |
|
---|
5 | namespace Netron.Diagramming.Core
|
---|
6 | {
|
---|
7 | // ----------------------------------------------------------------------
|
---|
8 | /// <summary>
|
---|
9 | /// The default connector. Represents an endpoint of a connection or a
|
---|
10 | /// location of a bundle to which a connection can be attached.
|
---|
11 | /// </summary>
|
---|
12 | // ----------------------------------------------------------------------
|
---|
13 | public partial class Connector : ConnectorBase
|
---|
14 | {
|
---|
15 | #region Fields
|
---|
16 |
|
---|
17 | // ------------------------------------------------------------------
|
---|
18 | /// <summary>
|
---|
19 | /// Implementation of IVersion - the current version of
|
---|
20 | /// Connector.
|
---|
21 | /// </summary>
|
---|
22 | // ------------------------------------------------------------------
|
---|
23 | protected const double connectorVersion = 1.0;
|
---|
24 |
|
---|
25 | // ------------------------------------------------------------------
|
---|
26 | /// <summary>
|
---|
27 | /// Specifies how the connector is drawn on the canvas when 'IsVisible'
|
---|
28 | /// is true. The default style is 'Simple', which is a transparent
|
---|
29 | /// background with a blue 'x' (similar to Visio).
|
---|
30 | /// </summary>
|
---|
31 | // ------------------------------------------------------------------
|
---|
32 | protected ConnectorStyle myStyle = ConnectorStyle.Simple;
|
---|
33 |
|
---|
34 | #endregion
|
---|
35 |
|
---|
36 | #region Properties
|
---|
37 |
|
---|
38 | // ------------------------------------------------------------------
|
---|
39 | /// <summary>
|
---|
40 | /// Gets the current version.
|
---|
41 | /// </summary>
|
---|
42 | // ------------------------------------------------------------------
|
---|
43 | public override double Version
|
---|
44 | {
|
---|
45 | get
|
---|
46 | {
|
---|
47 | return connectorVersion;
|
---|
48 | }
|
---|
49 | }
|
---|
50 |
|
---|
51 | // ------------------------------------------------------------------
|
---|
52 | /// <summary>
|
---|
53 | /// Gets or sets how the connector is drawn on the canvas when
|
---|
54 | /// 'IsVisible' is true.
|
---|
55 | /// </summary>
|
---|
56 | // ------------------------------------------------------------------
|
---|
57 | public ConnectorStyle ConnectorStyle
|
---|
58 | {
|
---|
59 | get
|
---|
60 | {
|
---|
61 | return this.myStyle;
|
---|
62 | }
|
---|
63 | set
|
---|
64 | {
|
---|
65 | this.myStyle = value;
|
---|
66 | }
|
---|
67 | }
|
---|
68 |
|
---|
69 | // ------------------------------------------------------------------
|
---|
70 | /// <summary>
|
---|
71 | /// Gets the friendly name of the entity to be displayed in the UI
|
---|
72 | /// </summary>
|
---|
73 | /// <value></value>
|
---|
74 | // ------------------------------------------------------------------
|
---|
75 | public override string EntityName
|
---|
76 | {
|
---|
77 | get { return "Connector"; }
|
---|
78 | }
|
---|
79 |
|
---|
80 | // ------------------------------------------------------------------
|
---|
81 | /// <summary>
|
---|
82 | /// The bounds of the paintable entity.
|
---|
83 | /// </summary>
|
---|
84 | /// <value></value>
|
---|
85 | // ------------------------------------------------------------------
|
---|
86 | public override Rectangle Rectangle
|
---|
87 | {
|
---|
88 | get
|
---|
89 | {
|
---|
90 | return new Rectangle(Point.X - 2, Point.Y - 2, 4, 4);
|
---|
91 | }
|
---|
92 | //set { Point = value.Location;
|
---|
93 | //TODO: think about what to do when setting the size }
|
---|
94 | }
|
---|
95 |
|
---|
96 | #endregion
|
---|
97 |
|
---|
98 | #region Constructor
|
---|
99 |
|
---|
100 | // ------------------------------------------------------------------
|
---|
101 | /// <summary>
|
---|
102 | /// Initializes a new instance of the <see cref="T:Connector"/> class.
|
---|
103 | /// </summary>
|
---|
104 | /// <param name="site">The site.</param>
|
---|
105 | // ------------------------------------------------------------------
|
---|
106 | public Connector(IModel site):base(site)
|
---|
107 | {
|
---|
108 | }
|
---|
109 |
|
---|
110 | // ------------------------------------------------------------------
|
---|
111 | /// <summary>
|
---|
112 | /// Initializes a new instance of the <see cref="T:Connector"/> class.
|
---|
113 | /// </summary>
|
---|
114 | /// <param name="p">The p.</param>
|
---|
115 | /// <param name="site">The site.</param>
|
---|
116 | // ------------------------------------------------------------------
|
---|
117 | public Connector(Point p, IModel site):base(p, site)
|
---|
118 | {
|
---|
119 | }
|
---|
120 |
|
---|
121 | // ------------------------------------------------------------------
|
---|
122 | /// <summary>
|
---|
123 | /// Initializes a new instance of the <see cref="T:Connector"/> class.
|
---|
124 | /// </summary>
|
---|
125 | /// <param name="p">The p.</param>
|
---|
126 | // ------------------------------------------------------------------
|
---|
127 | public Connector(Point p) : base(p)
|
---|
128 | {
|
---|
129 | }
|
---|
130 |
|
---|
131 | #endregion
|
---|
132 |
|
---|
133 | #region Methods
|
---|
134 |
|
---|
135 | // ------------------------------------------------------------------
|
---|
136 | /// <summary>
|
---|
137 | /// Paints the connector on the canvas.
|
---|
138 | /// </summary>
|
---|
139 | /// <param name="g"></param>
|
---|
140 | // ------------------------------------------------------------------
|
---|
141 | public override void Paint(Graphics g)
|
---|
142 | {
|
---|
143 | if (g == null)
|
---|
144 | {
|
---|
145 | throw new ArgumentNullException(
|
---|
146 | "The Graphics object is 'null'");
|
---|
147 | }
|
---|
148 |
|
---|
149 | if (Hovered || IsSelected)
|
---|
150 | {
|
---|
151 | Rectangle area = Rectangle;
|
---|
152 | area.Inflate(3, 3);
|
---|
153 | g.DrawRectangle(
|
---|
154 | ArtPalette.ConnectionHighlightPen,
|
---|
155 | area);
|
---|
156 | //g.FillRectangle(
|
---|
157 | // Brushes.Green,
|
---|
158 | // Point.X - 4,
|
---|
159 | // Point.Y - 4,
|
---|
160 | // 8,
|
---|
161 | // 8);
|
---|
162 | }
|
---|
163 | else
|
---|
164 | {
|
---|
165 | if (Visible)
|
---|
166 | {
|
---|
167 | switch (this.myStyle)
|
---|
168 | {
|
---|
169 | case ConnectorStyle.Simple :
|
---|
170 | DrawSimpleConnector(g);
|
---|
171 | break;
|
---|
172 |
|
---|
173 | case ConnectorStyle.Round :
|
---|
174 | break;
|
---|
175 |
|
---|
176 | case ConnectorStyle.Square :
|
---|
177 | break;
|
---|
178 | }
|
---|
179 |
|
---|
180 | if (this.mShowName)
|
---|
181 | {
|
---|
182 | DrawName(g);
|
---|
183 | }
|
---|
184 | }
|
---|
185 | }
|
---|
186 | }
|
---|
187 |
|
---|
188 | // ------------------------------------------------------------------
|
---|
189 | /// <summary>
|
---|
190 | /// Draws the name of this connector.
|
---|
191 | /// </summary>
|
---|
192 | /// <param name="g">Graphics</param>
|
---|
193 | // ------------------------------------------------------------------
|
---|
194 | void DrawName(Graphics g)
|
---|
195 | {
|
---|
196 | Size size = Size.Round(
|
---|
197 | g.MeasureString(mName, mFont));
|
---|
198 |
|
---|
199 | int xOffset = (size.Width - Rectangle.Width) / 2;
|
---|
200 | int yOffset = (size.Height - Rectangle.Height) / 2;
|
---|
201 |
|
---|
202 | System.Drawing.Point location = Rectangle.Location;
|
---|
203 |
|
---|
204 | switch (this.mNameLocation)
|
---|
205 | {
|
---|
206 | case ConnectorNameLocation.Top:
|
---|
207 | location = new Point(
|
---|
208 | Rectangle.X - xOffset,
|
---|
209 | Rectangle.Y - size.Height);
|
---|
210 | break;
|
---|
211 |
|
---|
212 | case ConnectorNameLocation.Bottom:
|
---|
213 | location = new Point(
|
---|
214 | Rectangle.X - xOffset,
|
---|
215 | Rectangle.Bottom + size.Height);
|
---|
216 | break;
|
---|
217 |
|
---|
218 | case ConnectorNameLocation.Left:
|
---|
219 | location = new Point(
|
---|
220 | Rectangle.X - size.Width,
|
---|
221 | Rectangle.Y - yOffset);
|
---|
222 | break;
|
---|
223 |
|
---|
224 | case ConnectorNameLocation.Right:
|
---|
225 | location = new Point(
|
---|
226 | Rectangle.Right,
|
---|
227 | Rectangle.Y - yOffset);
|
---|
228 | break;
|
---|
229 | }
|
---|
230 |
|
---|
231 | Rectangle textArea = new Rectangle(location, size);
|
---|
232 | StringFormat format = new StringFormat();
|
---|
233 | format.FormatFlags = StringFormatFlags.FitBlackBox;
|
---|
234 | g.DrawString(
|
---|
235 | mName,
|
---|
236 | mFont,
|
---|
237 | new SolidBrush(mForeColor),
|
---|
238 | location);
|
---|
239 | }
|
---|
240 |
|
---|
241 | // ------------------------------------------------------------------
|
---|
242 | /// <summary>
|
---|
243 | /// Draws a blue 'x' using 'Dot' as the line style, with a transparent
|
---|
244 | /// color.
|
---|
245 | /// </summary>
|
---|
246 | /// <param name="g">Graphics</param>
|
---|
247 | // ------------------------------------------------------------------
|
---|
248 | protected virtual void DrawSimpleConnector(Graphics g)
|
---|
249 | {
|
---|
250 | Pen pen = ArtPalette.GetSimpleConnectorPenStyle().DrawingPen();
|
---|
251 | Brush brush =
|
---|
252 | ArtPalette.GetSimpleConnectorPaintStyle().GetBrush(
|
---|
253 | this.Rectangle);
|
---|
254 |
|
---|
255 | GraphicsPath path = new GraphicsPath();
|
---|
256 | // Diagonal line from top left to bottom right.
|
---|
257 | g.DrawLine(pen, this.TopLeftCorner, this.BottomRightCorner);
|
---|
258 |
|
---|
259 |
|
---|
260 | // Diagonal line from top right to bottom lrft.
|
---|
261 | g.DrawLine(pen, this.TopRightCorner, this.BottomLeftCorner);
|
---|
262 | }
|
---|
263 |
|
---|
264 | // ------------------------------------------------------------------
|
---|
265 | /// <summary>
|
---|
266 | /// Tests if the mouse hits this connector.
|
---|
267 | /// </summary>
|
---|
268 | /// <param name="p">Point</param>
|
---|
269 | /// <returns>bool</returns>
|
---|
270 | // ------------------------------------------------------------------
|
---|
271 | public override bool Hit(Point p)
|
---|
272 | {
|
---|
273 | Point a = p;
|
---|
274 | Point b = Point;
|
---|
275 | b.Offset(-7,-7);
|
---|
276 | //a.Offset(-1,-1);
|
---|
277 | Rectangle r = new Rectangle(a,new Size(0,0));
|
---|
278 | Rectangle d = new Rectangle(b, new Size(15,15));
|
---|
279 | return d.Contains(r);
|
---|
280 | }
|
---|
281 |
|
---|
282 | // ------------------------------------------------------------------
|
---|
283 | /// <summary>
|
---|
284 | /// Invalidates the connector
|
---|
285 | /// </summary>
|
---|
286 | // ------------------------------------------------------------------
|
---|
287 | public override void Invalidate()
|
---|
288 | {
|
---|
289 | Point p = Point;
|
---|
290 | p.Offset(-5,-5);
|
---|
291 | if(Model!=null)
|
---|
292 | Model.RaiseOnInvalidateRectangle(
|
---|
293 | new Rectangle(p,new Size(10,10)));
|
---|
294 | }
|
---|
295 |
|
---|
296 | // ------------------------------------------------------------------
|
---|
297 | /// <summary>
|
---|
298 | /// Moves the connector with the given shift-vector.
|
---|
299 | /// </summary>
|
---|
300 | /// <param name="p">Point</param>
|
---|
301 | // ------------------------------------------------------------------
|
---|
302 | public override void MoveBy(Point p)
|
---|
303 | {
|
---|
304 | Point pt = new Point(this.Point.X + p.X, this.Point.Y + p.Y);
|
---|
305 | IConnection con = null;
|
---|
306 | Point p1 = Point.Empty, p2 = Point.Empty;
|
---|
307 |
|
---|
308 | Rectangle rec = new Rectangle(
|
---|
309 | Point.X - 10,
|
---|
310 | Point.Y - 10,
|
---|
311 | 20,
|
---|
312 | 20);
|
---|
313 |
|
---|
314 | this.Point = pt;
|
---|
315 |
|
---|
316 | #region Case of connection
|
---|
317 | if (typeof(IConnection).IsInstanceOfType(this.Parent))
|
---|
318 | {
|
---|
319 | (Parent as IConnection).Invalidate();
|
---|
320 | }
|
---|
321 | #endregion
|
---|
322 |
|
---|
323 | #region Case of attached connectors
|
---|
324 | for (int k = 0; k < AttachedConnectors.Count; k++)
|
---|
325 | {
|
---|
326 | if (typeof(IConnection).IsInstanceOfType(AttachedConnectors[k].Parent))
|
---|
327 | {
|
---|
328 | //keep a reference to the two points so we can invalidate the region afterwards
|
---|
329 | con = AttachedConnectors[k].Parent as IConnection;
|
---|
330 | p1 = con.From.Point;
|
---|
331 | p2 = con.To.Point;
|
---|
332 | }
|
---|
333 | AttachedConnectors[k].MoveBy(p);
|
---|
334 | if (con != null)
|
---|
335 | {
|
---|
336 | //invalidate the 'before the move'-region
|
---|
337 | Rectangle f = new Rectangle(p1, new Size(10, 10));
|
---|
338 | Rectangle t = new Rectangle(p2, new Size(10, 10));
|
---|
339 | Model.RaiseOnInvalidateRectangle(Rectangle.Union(f, t));
|
---|
340 | //finally, invalidate the region where the connection is now
|
---|
341 | (AttachedConnectors[k].Parent as IConnection).Invalidate();
|
---|
342 | }
|
---|
343 | }
|
---|
344 | #endregion
|
---|
345 | //invalidate this connector, since it's been moved
|
---|
346 | Invalidate(rec);//before the move
|
---|
347 | this.Invalidate();//after the move
|
---|
348 |
|
---|
349 | }
|
---|
350 |
|
---|
351 | // ------------------------------------------------------------------
|
---|
352 | /// <summary>
|
---|
353 | /// Moves the connector with the given shift-vector
|
---|
354 | /// </summary>
|
---|
355 | /// <param name="x">The x.</param>
|
---|
356 | /// <param name="y">The y.</param>
|
---|
357 | // ------------------------------------------------------------------
|
---|
358 | public void MoveBy(int x, int y)
|
---|
359 | {
|
---|
360 | Point pt = new Point( x, y);
|
---|
361 | MoveBy(pt);
|
---|
362 | }
|
---|
363 |
|
---|
364 | #endregion
|
---|
365 | }
|
---|
366 | }
|
---|