using System; using System.Drawing; using System.Drawing.Drawing2D; namespace Netron.Diagramming.Core { // ---------------------------------------------------------------------- /// /// The default connector. Represents an endpoint of a connection or a /// location of a bundle to which a connection can be attached. /// // ---------------------------------------------------------------------- public partial class Connector : ConnectorBase { #region Fields // ------------------------------------------------------------------ /// /// Implementation of IVersion - the current version of /// Connector. /// // ------------------------------------------------------------------ protected const double connectorVersion = 1.0; // ------------------------------------------------------------------ /// /// Specifies how the connector is drawn on the canvas when 'IsVisible' /// is true. The default style is 'Simple', which is a transparent /// background with a blue 'x' (similar to Visio). /// // ------------------------------------------------------------------ protected ConnectorStyle myStyle = ConnectorStyle.Simple; #endregion #region Properties // ------------------------------------------------------------------ /// /// Gets the current version. /// // ------------------------------------------------------------------ public override double Version { get { return connectorVersion; } } // ------------------------------------------------------------------ /// /// Gets or sets how the connector is drawn on the canvas when /// 'IsVisible' is true. /// // ------------------------------------------------------------------ public ConnectorStyle ConnectorStyle { get { return this.myStyle; } set { this.myStyle = value; } } // ------------------------------------------------------------------ /// /// Gets the friendly name of the entity to be displayed in the UI /// /// // ------------------------------------------------------------------ public override string EntityName { get { return "Connector"; } } // ------------------------------------------------------------------ /// /// The bounds of the paintable entity. /// /// // ------------------------------------------------------------------ public override Rectangle Rectangle { get { return new Rectangle(Point.X - 2, Point.Y - 2, 4, 4); } //set { Point = value.Location; //TODO: think about what to do when setting the size } } #endregion #region Constructor // ------------------------------------------------------------------ /// /// Initializes a new instance of the class. /// /// The site. // ------------------------------------------------------------------ public Connector(IModel site) : base(site) { } // ------------------------------------------------------------------ /// /// Initializes a new instance of the class. /// /// The p. /// The site. // ------------------------------------------------------------------ public Connector(Point p, IModel site) : base(p, site) { } // ------------------------------------------------------------------ /// /// Initializes a new instance of the class. /// /// The p. // ------------------------------------------------------------------ public Connector(Point p) : base(p) { } #endregion #region Methods // ------------------------------------------------------------------ /// /// Paints the connector on the canvas. /// /// // ------------------------------------------------------------------ public override void Paint(Graphics g) { if (g == null) { throw new ArgumentNullException( "The Graphics object is 'null'"); } if (Hovered || IsSelected) { Rectangle area = Rectangle; area.Inflate(3, 3); g.DrawRectangle( ArtPalette.ConnectionHighlightPen, area); //g.FillRectangle( // Brushes.Green, // Point.X - 4, // Point.Y - 4, // 8, // 8); } else { if (Visible) { switch (this.myStyle) { case ConnectorStyle.Simple: DrawSimpleConnector(g); break; case ConnectorStyle.Round: break; case ConnectorStyle.Square: DrawSquareConnector(g); break; } if (this.mShowName) { DrawName(g); } } } } // ------------------------------------------------------------------ /// /// Draws the name of this connector. /// /// Graphics // ------------------------------------------------------------------ void DrawName(Graphics g) { Size size = Size.Round( g.MeasureString(mName, mFont)); int xOffset = (size.Width - Rectangle.Width) / 2; int yOffset = (size.Height - Rectangle.Height) / 2; System.Drawing.Point location = Rectangle.Location; switch (this.mNameLocation) { case ConnectorNameLocation.Top: location = new Point( Rectangle.X - xOffset, Rectangle.Y - size.Height); break; case ConnectorNameLocation.Bottom: location = new Point( Rectangle.X - xOffset, Rectangle.Bottom + size.Height); break; case ConnectorNameLocation.Left: location = new Point( Rectangle.X - size.Width, Rectangle.Y - yOffset); break; case ConnectorNameLocation.Right: location = new Point( Rectangle.Right, Rectangle.Y - yOffset); break; } Rectangle textArea = new Rectangle(location, size); StringFormat format = new StringFormat(); format.FormatFlags = StringFormatFlags.FitBlackBox; g.DrawString( mName, mFont, new SolidBrush(mForeColor), location); } // ------------------------------------------------------------------ /// /// Draws a blue 'x' using 'Dot' as the line style, with a transparent /// color. /// /// Graphics // ------------------------------------------------------------------ protected virtual void DrawSimpleConnector(Graphics g) { Pen pen = ArtPalette.GetSimpleConnectorPenStyle().DrawingPen(); Brush brush = ArtPalette.GetSimpleConnectorPaintStyle().GetBrush( this.Rectangle); GraphicsPath path = new GraphicsPath(); // Diagonal line from top left to bottom right. g.DrawLine(pen, this.TopLeftCorner, this.BottomRightCorner); // Diagonal line from top right to bottom lrft. g.DrawLine(pen, this.TopRightCorner, this.BottomLeftCorner); } protected virtual void DrawSquareConnector(Graphics g) { Pen pen = ArtPalette.GetSimpleConnectorPenStyle().DrawingPen(); Brush brush = ArtPalette.GetSimpleConnectorPaintStyle().GetBrush(this.Rectangle); g.DrawRectangle(pen, this.Rectangle); } // ------------------------------------------------------------------ /// /// Tests if the mouse hits this connector. /// /// Point /// bool // ------------------------------------------------------------------ public override bool Hit(Point p) { Point a = p; Point b = Point; b.Offset(-7, -7); //a.Offset(-1,-1); Rectangle r = new Rectangle(a, new Size(0, 0)); Rectangle d = new Rectangle(b, new Size(15, 15)); return d.Contains(r); } // ------------------------------------------------------------------ /// /// Invalidates the connector /// // ------------------------------------------------------------------ public override void Invalidate() { Point p = Point; p.Offset(-5, -5); if (Model != null) Model.RaiseOnInvalidateRectangle( new Rectangle(p, new Size(10, 10))); } // ------------------------------------------------------------------ /// /// Moves the connector with the given shift-vector. /// /// Point // ------------------------------------------------------------------ public override void MoveBy(Point p) { Point pt = new Point(this.Point.X + p.X, this.Point.Y + p.Y); IConnection con = null; Point p1 = Point.Empty, p2 = Point.Empty; Rectangle rec = new Rectangle( Point.X - 10, Point.Y - 10, 20, 20); this.Point = pt; #region Case of connection if (typeof(IConnection).IsInstanceOfType(this.Parent)) { (Parent as IConnection).Invalidate(); } #endregion #region Case of attached connectors for (int k = 0; k < AttachedConnectors.Count; k++) { if (typeof(IConnection).IsInstanceOfType(AttachedConnectors[k].Parent)) { //keep a reference to the two points so we can invalidate the region afterwards con = AttachedConnectors[k].Parent as IConnection; p1 = con.From.Point; p2 = con.To.Point; } AttachedConnectors[k].MoveBy(p); if (con != null) { //invalidate the 'before the move'-region Rectangle f = new Rectangle(p1, new Size(10, 10)); Rectangle t = new Rectangle(p2, new Size(10, 10)); Model.RaiseOnInvalidateRectangle(Rectangle.Union(f, t)); //finally, invalidate the region where the connection is now (AttachedConnectors[k].Parent as IConnection).Invalidate(); } } #endregion //invalidate this connector, since it's been moved Invalidate(rec);//before the move this.Invalidate();//after the move } // ------------------------------------------------------------------ /// /// Moves the connector with the given shift-vector /// /// The x. /// The y. // ------------------------------------------------------------------ public void MoveBy(int x, int y) { Point pt = new Point(x, y); MoveBy(pt); } #endregion } }