Every Entity will have potentially 8 vertex each one could have also more than one connection.
public enum VertexPosition { None, TopLeft, TopRight, TopMiddle, BottomLeft, BottomMiddle, BottomRight, MiddleLeft, MiddleRight }
So I imagined a class called FCBaseControl where to put a List of Connections and a Text property. Simple but efficient.
• Connections get or set Connection items to define relations both graphics and logics.
• Caption get or set a Text description that appear into the Entity area.
The FCBaseControl expose also two Method:
public Point GetVertex(VertexPosition ePosition, int iDistance = 5)
GetVertex() return the coordinates (Point) of a given Vertex, while GetAutomaticPositions() get the best Vertex to connect c1 to c2 without overlapping. Connection object represent a logical relation and an hypothetic graphical connection, because the graphical connection can be changed run-time as I will show you in this article.
One event it is also published, this is for redrawing run-time the Entity object.
public event LocationDraggedEvent LocationDragged;
The next step will be build a control that will provide all redrawing activities without any operator iterations. A canvas where to paint our “pictures”. This object is called FCCanvasPanel and it is a simple UserControl derived class.
The ParentControlDesigner reference extends the design mode behavior of a Control that supports nested controls, otherwise it should be impossible to manage other controls inside it. As I mentioned before this control should be able to redraw the connections with also the ability of a clever redrawing. Property AutoConnect enable the clever redrawing.
This very simple object will do the dirty job on the backstage.
This is the private Method that do the job:
NOTE: I add this note in order to say sorry to the readers, because for commercial reason I cannot divulge more informations. I hope these two post can inspire you to develop a more complex library.
Part 1
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))] public partial class FCCanvasPanel : UserControl
The ParentControlDesigner reference extends the design mode behavior of a Control that supports nested controls, otherwise it should be impossible to manage other controls inside it. As I mentioned before this control should be able to redraw the connections with also the ability of a clever redrawing. Property AutoConnect enable the clever redrawing.
This very simple object will do the dirty job on the backstage.
This is the private Method that do the job:
private void DrawConnections() { PaintElement draw = new PaintElement(this.CreateGraphics()); draw.Color = Color.Black; foreach (var item in this.Controls) { if (item is FCControlBase) { FCControlBase c1 = (FCControlBase)item; foreach (Connection con in c1.Connections) { Point p1 = new Point(); Point p2 = new Point(); if (con.Child != null) { if (AutoConnect) { FCControlBase c2 = (FCControlBase)con.Child; VertexPosition or, dest; FCControlBase.GetAutomaticPositions(c1, c2, out or, out dest); if (or == VertexPosition.None || dest == VertexPosition.None) continue; p1 = c1.GetVertex(or, 10);//c1.GetVertex(con.Origin, 10); p2 = c2.GetVertex(dest, 5); //c2.GetVertex(con.Destination, 5); } else { p1 = c1.GetVertex(con.Origin, 10); FCControlBase c2 = (FCControlBase)con.Child; p2 = c2.GetVertex(con.Destination, 5); } draw.Color = con.Color; if (con.Type == ConjunctionType.Arrow) draw.Arrow(p1, p2); else if (con.Type == ConjunctionType.Line) draw.Line(p1, p2); if (con.Text != "") { Point pMid = draw.GetMiddle(p1, p2); double dAngle = draw.GetAngle(p1, p2); RecalcTextPointByAngle(dAngle, ref pMid); draw.Text(pMid, con.Text, new Font("Arial", 8), Color.Black); } } } } } }
NOTE: I add this note in order to say sorry to the readers, because for commercial reason I cannot divulge more informations. I hope these two post can inspire you to develop a more complex library.
Part 1