/*public override void PaintValue(PaintValueEventArgs e) * { * e.Graphics.FillRectangle(Brushes.White, e.Bounds); * if (e.Value is LineAnchor && ((LineCap)e.Value) != LineCap.Flat) * { * Pen pen = new Pen(Color.Black, 5); * Point pt = PaintHelper.CenterPoint(e.Bounds); * if (IsEndCap) * { * pen.EndCap = (LineCap)e.Value; * e.Graphics.DrawLine(pen, e.Bounds.Left + 2, pt.Y, e.Bounds.Right - pen.Width - 2, pt.Y); * } * else * { * pen.StartCap = (LineCap)e.Value; * e.Graphics.DrawLine(pen, e.Bounds.Left + pen.Width + 2, pt.Y, e.Bounds.Right - 2, pt.Y); * } * } * }*/ protected override void DrawListItem(DrawItemEventArgs e, Rectangle rect, ListItem <LineAnchor> listItem) { var value = listItem.Value; //base.DrawItem(e, rect, value); if (value != LineAnchor.None) { Color foreColor = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ? SystemColors.HighlightText : SystemColors.WindowText; Point pt = PaintHelper.CenterPoint(rect); rect.Inflate(-10, 0); rect.X += 5; rect.Width -= 5; IGraphics grf = new GdiGraphics(e.Graphics); var gs = grf.Save(); grf.SetHighQualityRender(); var pen = grf.Pen(foreColor, 5); if (IsEndCap) { grf.DrawLine(pen, rect.Left, pt.Y, rect.Right, pt.Y, LineAnchor.None, (LineAnchor)value); } else { grf.DrawLine(pen, rect.Left, pt.Y, rect.Right, pt.Y, (LineAnchor)value, LineAnchor.None); } grf.Restore(gs); } }
/*public void GeneralSvg(XmlElement parentNode, Rectangle rectFrom, Rectangle rectTo, Vector4 vectorFrom, Vector4 vectorTo, Color color) * { * Point[] pts = GetPoints(rectFrom, rectTo, vectorFrom, vectorTo); * if (pts == null) * return; * * StringBuilder sb = new StringBuilder(); * sb.AppendFormat("M{0},{1} ", pts[0].X, pts[0].Y); * sb.AppendFormat("C{0},{1} {2},{3} {4},{5}", pts[1].X, pts[1].Y, pts[2].X, pts[2].Y, pts[3].X, pts[3].Y); * * XmlElement path = parentNode.OwnerDocument.CreateElement("path"); * path.SetAttribute("d", sb.ToString()); * path.SetAttribute("fill", "none"); * parentNode.AppendChild(path); * * if (!color.IsEmpty) * path.SetAttribute("stroke", ST.ToString(color)); * }*/ private Point[] GetPoints(Rectangle rectFrom, Rectangle rectTo, Vector4 vector, Vector4 vectorTo) { Point org = PaintHelper.CenterPoint(rectFrom); Point to = PaintHelper.CenterPoint(rectTo); double dis = IsRoot ? ArrowBase : ArrowBase / 3; // Point startPoint = GetOffsetPoint(org, to, dis); Point point4 = GetRandomPoint(org, to, 0.5, this.rand1); Point point5 = GetRandomPoint(to, org, 0.5, this.rand2); Point point6 = GetOffsetPoint(org, to, -dis); Point point7 = GetOffsetPoint(point4, to, -5.0); Point pt = GetOffsetPoint(to, org, -2.0); Point pt2 = GetOffsetPoint(to, org, 1.0); // return(new Point[] { startPoint, point4, point5, pt, pt2, point5, point7, point6, }); }
Point[] GetPoints(Rectangle rectFrom, Rectangle rectTo, Vector4 vectorFrom, Vector4 vectorTo) { Point ptF = PaintHelper.CenterPoint(rectFrom); Point ptT = PaintHelper.CenterPoint(rectTo); Point[] pts = new Point[4]; switch (vectorFrom) { case Vector4.Left: pts[0] = new Point(rectFrom.Left, ptF.Y); pts[1] = new Point(rectFrom.Left - (rectFrom.Left - rectTo.Right) / 2, ptF.Y); pts[2] = new Point(rectFrom.Left - (rectFrom.Left - rectTo.Right) / 2, ptT.Y); pts[3] = new Point(rectTo.Right, ptT.Y); break; case Vector4.Top: pts[0] = new Point(ptF.X, rectFrom.Top); pts[1] = new Point(ptF.X, rectFrom.Top - (rectFrom.Top - rectTo.Bottom) / 2); pts[2] = new Point(ptT.X, rectFrom.Top - (rectFrom.Top - rectTo.Bottom) / 2); pts[3] = new Point(ptT.X, rectTo.Bottom); break; case Vector4.Right: pts[0] = new Point(rectFrom.Right, ptF.Y); pts[1] = new Point(rectFrom.Right + (rectTo.Left - rectFrom.Right) / 2, ptF.Y); pts[2] = new Point(rectFrom.Right + (rectTo.Left - rectFrom.Right) / 2, ptT.Y); pts[3] = new Point(rectTo.Left, ptT.Y); break; case Vector4.Bottom: pts[0] = new Point(ptF.X, rectFrom.Bottom); switch (vectorTo) { case Vector4.Left: pts[1] = new Point(ptF.X, ptT.Y); pts[2] = pts[1]; pts[3] = new Point(rectTo.Left, ptT.Y); break; case Vector4.Right: pts[1] = new Point(ptF.X, ptT.Y); pts[2] = pts[1]; pts[3] = new Point(rectTo.Right, ptT.Y); break; default: pts[1] = new Point(ptF.X, rectFrom.Bottom + (rectTo.Top - rectFrom.Bottom) / 2); pts[2] = new Point(ptT.X, rectFrom.Bottom + (rectTo.Top - rectFrom.Bottom) / 2); pts[3] = new Point(ptT.X, rectTo.Top); break; } break; default: break; } return(pts); }
public override void OnMouseMove(ExMouseEventArgs e) { base.OnMouseMove(e); if (NewLineFrom != null) { Point pt = PaintHelper.CenterPoint(NewLineFrom.Bounds); pt = View.PointToReal(pt); Rectangle rect = PaintHelper.GetRectangle(pt, MousePoint); rect = Rectangle.Union(rect, PaintHelper.GetRectangle(pt, new Point(e.X, e.Y))); MousePoint.X = e.X; MousePoint.Y = e.Y; InvalidateChart(rect, false); } else { // test - is drag control handle if (PressMouseButton == MouseButtons.Left && SelectedObject.ControlHandle != BezierPoint.None) { DragControlHandle(SelectedObject.ControlHandle, new Point(e.X, e.Y)); e.Suppress = true; if (View.Cursor != Cursors.SizeAll) { View.Cursor = Cursors.SizeAll; } } else { HoverObject = HitTest(e.X, e.Y); // test - is open url if (HoverObject.Link != null && Helper.TestModifierKeys(Keys.Shift) && !string.IsNullOrEmpty(HoverObject.Link.Hyperlink)) { e.Suppress = true; if (View.Cursor != Cursors.Hand) { View.Cursor = Cursors.Hand; } } else if (HoverObject.ControlHandle != BezierPoint.None) { if (View.Cursor != Cursors.SizeAll) { View.Cursor = Cursors.SizeAll; } e.Suppress = true; } //else //View.Cursor = Cursors.Default; } } }
Point[] GetPointsForRoot(TopicShape shapeFrom, TopicShape shapeTo, Rectangle rectFrom, Rectangle rectTo, Vector4 vector, Vector4 vectorTo) { var fcp = PaintHelper.CenterPoint(rectFrom); int bezierTurn; Point[] pts = new Point[4]; switch (vector) { case Vector4.Left: bezierTurn = Math.Min(MaxBezierTurn, Math.Abs(rectTo.Right - rectFrom.Left)); pts[3] = new Point(rectTo.Right, rectTo.Y + rectTo.Height / 2); pts[2] = new Point(rectTo.Right + bezierTurn, pts[3].Y); break; case Vector4.Right: bezierTurn = Math.Min(MaxBezierTurn, Math.Abs(rectTo.Left - rectFrom.Right)); pts[3] = new Point(rectTo.X, rectTo.Y + rectTo.Height / 2); pts[2] = new Point(rectTo.X - bezierTurn, pts[3].Y); break; case Vector4.Top: bezierTurn = Math.Min(MaxBezierTurn, Math.Abs(rectFrom.Top - rectTo.Bottom)); pts[3] = new Point(rectTo.X + rectTo.Width / 2, rectTo.Bottom); pts[2] = new Point(rectTo.X + rectTo.Width / 2, rectTo.Bottom + bezierTurn); break; case Vector4.Bottom: bezierTurn = Math.Min(MaxBezierTurn, Math.Abs(rectTo.Top - rectFrom.Bottom)); pts[3] = new Point(rectTo.X + rectTo.Width / 2, rectTo.Top); pts[2] = new Point(rectTo.X + rectTo.Width / 2, rectTo.Top - bezierTurn); break; } Point?startPoint; if (shapeFrom == TopicShape.Ellipse) { startPoint = PaintHelper.GetPointForPointIntersectEllipse(rectFrom, pts[3]); } else { startPoint = PaintHelper.GetPointForLineIntersectRectangle(rectFrom, pts[3]); } if (!startPoint.HasValue) { return(null); } pts[0] = startPoint.Value; pts[1] = startPoint.Value; return(pts); }
public override void PaintValue(PaintValueEventArgs e) { e.Graphics.FillRectangle(Brushes.White, e.Bounds); bool isend = e.Context.PropertyDescriptor.Name == "EndCap"; Pen pen = new Pen(Color.Black, 2); pen.DashStyle = (DashStyle)e.Value; Point pt = PaintHelper.CenterPoint(e.Bounds); e.Graphics.DrawLine(pen, e.Bounds.Left + 2, pt.Y, e.Bounds.Right - 2, pt.Y); }
void DrawNewLineTest(Topic from, PaintEventArgs e) { Point pt = PaintHelper.CenterPoint(from.Bounds); pt = View.PointToReal(pt); Pen pen = new Pen(Color.FromArgb(100, Map.LinkLineColor), 3); pen.StartCap = LineCap.RoundAnchor; pen.EndCap = LineCap.ArrowAnchor; e.Graphics.DrawLine(pen, pt, MousePoint); }
public void Reset() { Point ptf = PaintHelper.CenterPoint(From.Bounds); Point ptt = PaintHelper.CenterPoint(Target.Bounds); int distance = PaintHelper.GetDistance(ptf, ptt); var len = distance * 20 / 100; var angle = PaintHelper.GetAngle(ptf, ptt); LayoutData.CP1 = new BezierControlPoint(angle, len); LayoutData.CP2 = new BezierControlPoint((180 + angle) % 360, len); RefreshLayout(); SetChanged(); }
protected override void DrawListItem(DrawItemEventArgs e, Rectangle rect, ListItem <DashStyle> listItem) { var value = listItem.Value; //base.DrawListItem(e, rect, value); Color foreColor = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ? SystemColors.HighlightText : SystemColors.WindowText; Point pt = PaintHelper.CenterPoint(rect); rect.Inflate(-4, 0); Pen pen = new Pen(foreColor, 2); pen.DashStyle = value; e.Graphics.DrawLine(pen, rect.Left, pt.Y, rect.Left + 60, pt.Y); rect.X += 70; rect.Width -= 70; DrawItemText(e, rect, listItem.Text); }
Point[] GetPoints(Rectangle rectFrom, Rectangle rectTo, Vector4 vector, Vector4 vectorTo) { int bezierTurn = 20; Point fcp = PaintHelper.CenterPoint(rectFrom); Point tcp = PaintHelper.CenterPoint(rectTo); int distance = PaintHelper.GetDistance(fcp, tcp); //bezierTurn = distance / 5; // 20% Point[] pts; switch (vector) { case Vector4.Left: distance = PaintHelper.GetDistance(new Point(rectFrom.Left, fcp.Y), new Point(rectTo.Right, tcp.Y)); bezierTurn = Math.Min(MaxBezierTurn, Math.Abs(rectFrom.Left - rectTo.Right)); pts = new Point[] { new Point(rectFrom.Left, fcp.Y), new Point(rectFrom.Left - bezierTurn, fcp.Y), new Point(rectTo.Right + bezierTurn, tcp.Y), new Point(rectTo.Right, tcp.Y) }; break; case Vector4.Top: distance = PaintHelper.GetDistance(new Point(fcp.X, rectFrom.Top), new Point(tcp.X, rectTo.Bottom)); bezierTurn = Math.Min(MaxBezierTurn, Math.Abs(rectTo.Bottom - rectFrom.Top)); pts = new Point[] { new Point(fcp.X, rectFrom.Top), new Point(fcp.X, rectFrom.Top - bezierTurn), new Point(tcp.X, rectTo.Bottom + bezierTurn), new Point(tcp.X, rectTo.Bottom) }; break; case Vector4.Right: distance = PaintHelper.GetDistance(new Point(rectFrom.Right, fcp.Y), new Point(rectTo.Left, tcp.Y)); bezierTurn = Math.Min(MaxBezierTurn, Math.Abs(rectTo.Left - rectFrom.Right)); // distance / 5; // 20% pts = new Point[] { new Point(rectFrom.Right, fcp.Y), new Point(rectFrom.Right + bezierTurn, fcp.Y), new Point(rectTo.Left - bezierTurn, tcp.Y), new Point(rectTo.Left, tcp.Y) }; break; case Vector4.Bottom: distance = PaintHelper.GetDistance(new Point(fcp.X, rectFrom.Bottom), new Point(tcp.X, rectTo.Top)); bezierTurn = Math.Min(MaxBezierTurn, Math.Abs(rectFrom.Bottom - rectTo.Top)); pts = new Point[] { new Point(fcp.X, rectFrom.Bottom), new Point(fcp.X, rectFrom.Bottom - bezierTurn), new Point(tcp.X, rectTo.Top + bezierTurn), new Point(tcp.X, rectTo.Top) }; break; default: pts = null; break; } return(pts); }
Rectangle LayoutSubTopics(Topic parent, Topic[] subTopics, Vector4 vector, XList <int> rows, XList <int> columns, int parentRow, int parentCol, MindMapLayoutArgs e) { if (parent == null) { throw new ArgumentNullException(); } if (rows.IsEmpty || columns.IsEmpty) { return(Rectangle.Empty); } if (parent.Folded || parent.Children.IsEmpty) { return(Rectangle.Empty); } int vSpace = e.ItemsSpace; Topic root = parent.GetRoot(); Rectangle rectFull = Rectangle.Empty; Point pp = PaintHelper.CenterPoint(root.ContentBounds); int fullHeight = GetYPos(rows.Count - 1, vSpace, rows); int x = vector == Vector4.Left ? root.Left - e.LayerSpace : root.Right + e.LayerSpace; int y = pp.Y - (fullHeight / 2) - 30; int hSpace = 10; Topic previous = parent == root ? root : parent.ParentTopic; int prevRow = 0; for (int i = 0, n = subTopics.Length; i < n; ++i) { Topic subTopic = subTopics[i]; subTopic.Vector = vector; int row = 0, column = 0; switch (vector) { case Vector4.Top: subTopic.Location = new Point(root.Bounds.Left - (subTopic.Width - root.Width) / 2, parent.Location.Y - e.LayerSpace - subTopic.Size.Height); break; case Vector4.Left: case Vector4.Right: default: if (subTopic.Type == TopicType.Barrier) { column = parentCol - subTopics.Length + i; row = parentRow; } else { column = parentCol + (subTopic.Folded ? 0 : subTopic.Children.Count) + 1; row = parentRow + 1; if (subTopic.Type == TopicType.Escalation) { int maxUncleRow = 0; if (parent.ParentTopic != null) { XList <Topic> children = parent.ParentTopic.Children; int nextIndex = children.IndexOf(parent) + 1; if (nextIndex < children.Count) { maxUncleRow = CalculateMaxRow(children[nextIndex], children.ToArray()); } } int maxSiblingRow = 0; int prevIndex = i - 1; if (prevIndex >= 0) { maxSiblingRow = CalculateMaxRow(parent.Children[prevIndex], parent.Children.ToArray()); } row += maxSiblingRow + maxUncleRow; } else if (parent.IsRoot) { int prevIndex = i - 1; if (prevIndex >= 0) { row += CalculateMaxRow(subTopics[prevIndex], subTopics); } } } Point pt = new Point(GetXPos(column, hSpace, columns, vector), GetYPos(row, vSpace, rows)); if (subTopic.Type == TopicType.Barrier) { if (vector == Vector4.Left) { pt.X -= (subTopic.ContentBounds.Width - subTopic.Width) / 2; } else { pt.X += (subTopic.ContentBounds.Width - subTopic.Width) / 2; } } subTopic.Location = new Point(vector == Vector4.Left ? x - pt.X: x + pt.X, pt.Y + y); prevRow = row; break; } // line if (!parent.Folded && subTopic.Type == TopicType.Barrier) { var lines = CreateTopicLines(e, previous, subTopic, vector, GetReverseVector(vector)); if (lines != null) { parent.Lines.AddRange(lines); } } subTopic.Lines.Clear(); Rectangle rectFullSub = LayoutSubTopics(subTopic, subTopic.Children.ToArray(), vector, rows, columns, row, column, e); // Threat topic will be drawn as the last element if (subTopic.Type == TopicType.Threat || subTopic.Type == TopicType.Consequence || subTopic.Type == TopicType.Escalation) { Topic beginNode, endNode; if (subTopic.HasChildren && !subTopic.Folded) { beginNode = subTopic.Children[subTopic.Children.Count - 1]; endNode = subTopic; } else { beginNode = parent; endNode = subTopic; } var lines = CreateTopicLines(e, beginNode, endNode, vector, GetReverseVector(vector)); if (lines != null) { beginNode.Lines.AddRange(lines); } if (subTopic.HasChildren) { int foldBtnSize = FoldingButtonSize; if (vector == Vector4.Left) { subTopic.FoldingButton = new Rectangle(subTopic.Right - foldBtnSize + 4, subTopic.Top + (int)Math.Round((60 - foldBtnSize) / 2.0f, MidpointRounding.AwayFromZero), foldBtnSize, foldBtnSize); } else if (vector == Vector4.Right) { subTopic.FoldingButton = new Rectangle(subTopic.Left - foldBtnSize + 4, subTopic.Top + (int)Math.Round((60 - foldBtnSize) / 2.0f, MidpointRounding.AwayFromZero), foldBtnSize, foldBtnSize); } } } else if (subTopic.Type == TopicType.Hazard) { var lines = CreateTopicLines(e, root, subTopic, vector, GetReverseVector(vector)); if (lines != null) { root.Lines.AddRange(lines); } } rectFull = Rectangle.Union(rectFull, subTopic.ContentBounds); if (!rectFullSub.IsEmpty) { rectFull = Rectangle.Union(rectFull, rectFullSub); } previous = subTopic; } return(rectFull); }
Rectangle LayoutSubTopics(Topic parent, Topic[] subTopics, Vector4 vector, Hashtable layoutInfos, MindMapLayoutArgs e) { if (parent == null) { throw new ArgumentNullException(); } if (!layoutInfos.Contains(parent)) { return(Rectangle.Empty); } if (parent.Folded || parent.Children.IsEmpty) { return(Rectangle.Empty); } int nodeSpace = e.ItemsSpace; if (parent.IsRoot) { nodeSpace = GetRootItemsSpace(parent, subTopics, layoutInfos, e); } // get full height //int nodeSpace = (int)((parent.IsRoot ? NodeSpaceRoot_V : NodeSpace_V) * args.Zoom); int fullHeight = 0; for (int i = 0; i < subTopics.Length; i++) { if (i > 0) { fullHeight += nodeSpace; } fullHeight += ((TopicLayoutInfo)layoutInfos[subTopics[i]]).FullSize.Height; } // Rectangle rectFull = Rectangle.Empty; Point pp = PaintHelper.CenterPoint(parent.Bounds); int y = pp.Y - (fullHeight / 2); //int space = (int)(NodeSpace_H * args.Zoom); int space = e.LayerSpace; foreach (var subTopic in subTopics) { var subTif = (TopicLayoutInfo)layoutInfos[subTopic]; subTopic.Vector = vector == Vector4.Left ? Vector4.Left : Vector4.Right; Point pt; switch (vector) { case Vector4.Left: pt = new Point(parent.Bounds.Left - space - subTopic.Bounds.Width, y + (subTif.FullSize.Height) / 2); break; case Vector4.Right: default: pt = new Point(parent.Bounds.Right + space, y + (subTif.FullSize.Height) / 2); break; } subTopic.Location = new Point(pt.X, pt.Y - subTopic.Size.Height / 2); int foldBtnSize = FoldingButtonSize; switch (vector) { case Vector4.Left: subTopic.FoldingButton = new Rectangle(subTopic.Left - foldBtnSize - 1, subTopic.Top + (int)Math.Round((subTopic.Height - foldBtnSize) / 2.0f, MidpointRounding.AwayFromZero), foldBtnSize, foldBtnSize); break; case Vector4.Right: default: subTopic.FoldingButton = new Rectangle(subTopic.Right + 1, subTopic.Top + (int)Math.Round((subTopic.Height - foldBtnSize) / 2.0f, MidpointRounding.AwayFromZero), foldBtnSize, foldBtnSize); break; } // line var line = CreateTopicLine(e, parent, subTopic, vector, GetReverseVector(vector)); if (line != null) { parent.Lines.Add(line); } //parent.Lines.Add(new TopicLine(subTopic, vector, GetReverseVector(vector))); subTopic.Lines.Clear(); Rectangle rectFullSub = LayoutSubTopics(subTopic, subTopic.Children.ToArray(), vector, layoutInfos, e); rectFull = Rectangle.Union(rectFull, subTopic.Bounds); if (!rectFullSub.IsEmpty) { rectFull = Rectangle.Union(rectFull, rectFullSub); } y += subTif.FullSize.Height + nodeSpace; } return(rectFull); }
public override void OnMouseUp(ExMouseEventArgs e) { base.OnMouseUp(e); PressMouseButton = MouseButtons.None; //MouseDownObject = HitTestResult.Empty; if (NewLineFrom != null) { EndNewLineTest(e); e.Suppress = true; } else if (e.Button == MouseButtons.Left && PressedObject.Link != null && Helper.TestModifierKeys(Keys.Shift)) { if (!string.IsNullOrEmpty(PressedObject.Link.Hyperlink)) { Helper.OpenUrl(PressedObject.Link.Hyperlink); } } else { if (DragingControlHandle != BezierPoint.None && TempLayout != null && SelectedObject.Link != null) { Link line = SelectedObject.Link; var oldPoints = line.GetBezierPoints(); //Rectangle rect = line.Bounds; Point pt = View.PointToLogic(new Point(e.X, e.Y)); Point pts; Topic topic; switch (DragingControlHandle) { case BezierPoint.StartPoint: topic = View.GetTopicAt(e.X, e.Y); if (line.CanStartFrom(topic)) { line.From = topic; } break; case BezierPoint.EndPoint: topic = View.GetTopicAt(e.X, e.Y); if (line.CanEndTo(topic)) { line.Target = topic; } break; case BezierPoint.ControlPoint1: pts = PaintHelper.CenterPoint(line.LayoutData.StartBounds); //line.LayoutData.CPLength1 = PaintHelper.GetDistance(pts, pt); //line.LayoutData.CPAngle1 = PaintHelper.GetAngle(pts, pt); line.LayoutData.CP1 = new BezierControlPoint(PaintHelper.GetAngle(pts, pt), PaintHelper.GetDistance(pts, pt)); break; case BezierPoint.ControlPoint2: pts = PaintHelper.CenterPoint(line.LayoutData.EndBounds); //line.LayoutData.CPLength2 = PaintHelper.GetDistance(pts, pt); //line.LayoutData.CPAngle2 = PaintHelper.GetAngle(pts, pt); line.LayoutData.CP2 = new BezierControlPoint(PaintHelper.GetAngle(pts, pt), PaintHelper.GetDistance(pts, pt)); break; } line.RefreshLayout(); line.SetChanged(); TempLayout = line.LayoutData.Clone(); InvalidateLink(oldPoints, line.Width, true); InvalidateLink(line, false); //InvalidateLinkRegion(oldPoints, line.GetBezierPoints(), line.LineWidth); /*if (rect.IsEmpty) * rect = line.Bounds; * else * rect = Rectangle.Union(rect, line.Bounds); * rect.Location = View.PointToReal(rect.Location); * InvalidateChart(rect, true);*/ } DragingControlHandle = BezierPoint.None; } }
BezierLayoutInfo GetLayoutInfo(BezierControlPoint controlPoint1, BezierControlPoint controlPoint2) { var layout = new BezierLayoutInfo(); layout.CP1 = controlPoint1; layout.CP2 = controlPoint2; Point cp1, cp2; Rectangle rect1 = From.Bounds; Rectangle rect2 = Target.Bounds; Point pts = PaintHelper.CenterPoint(rect1); Point ptd = PaintHelper.CenterPoint(rect2); rect1.Inflate(2, 2); rect2.Inflate(2, 2); if (StartCap != LineAnchor.None) { rect1.Inflate(Layouter.LineAnchorSize, Layouter.LineAnchorSize); } if (EndCap != LineAnchor.None) { rect2.Inflate(Layouter.LineAnchorSize, Layouter.LineAnchorSize); } if (pts == ptd) { cp1 = pts; cp2 = ptd; layout.Bounds = Rectangle.Empty; layout.Region = null; } else { cp1 = BezierHelper.GetControlPoint(pts, controlPoint1); cp2 = BezierHelper.GetControlPoint(ptd, controlPoint2); //Point[] controlPoints = GetControlPoints(pts, ptd); Shape sShape = Shape.GetShaper(From); pts = sShape.GetBorderPoint(rect1, cp1); Shape dShape = Shape.GetShaper(Target); ptd = sShape.GetBorderPoint(rect2, cp2); GraphicsPath gp = new GraphicsPath(); gp.AddBezier(pts, cp1, cp2, ptd); Pen penWiden = new Pen(Color.Black, LineWidth + 5); gp.Widen(penWiden); var rect = gp.GetBounds(); rect.Inflate(LineWidth, LineWidth); layout.Bounds = rect; layout.Region = new Region(gp); } Point ptCenter = BezierHelper.GetPoint(pts, cp1, cp2, ptd, 0.5f); Rectangle textBounds = layout.TextBounds; textBounds.X = ptCenter.X - layout.TextBounds.Width / 2; textBounds.Y = ptCenter.Y - layout.TextBounds.Height / 2; // cache layout info layout.StartBounds = rect1; layout.EndBounds = rect2; layout.StartPoint = pts; layout.EndPoint = ptd; layout.ControlPoint1 = cp1; layout.ControlPoint2 = cp2; layout.TextBounds = textBounds; return(layout); }