public ConnectorPoint BreakAtPoint(Point point, int?brokenSegment = null) { if (brokenSegment == null) { brokenSegment = GeometryHelper.FindHitSegmentIndex(point, this.Points); } ConnectorPoint connectorPoint = new ConnectorPoint(ExolutioCanvas); connectorPoint.OrderInConnector = brokenSegment.Value + 1; connectorPoint.Placement = EPlacementKind.AbsoluteCanvas; connectorPoint.Connector = this; ExolutioCanvas.Children.Add(connectorPoint); connectorPoint.SetPreferedPosition(point); ExolutioContextMenu exolutioContextMenu = new ExolutioContextMenu(); ContextMenuItem cStraighten = new ContextMenuItem("Straighten line here"); cStraighten.Tag = connectorPoint; cStraighten.Click += delegate(object sender, RoutedEventArgs e) { ConnectorPoint clickedPoint = (ConnectorPoint)((ContextMenuItem)sender).Tag; StraightenLineAtPoint(clickedPoint); }; exolutioContextMenu.Items.Add(cStraighten); connectorPoint.ContextMenu = exolutioContextMenu; foreach (ConnectorPoint cp in Points) { if (cp.OrderInConnector >= connectorPoint.OrderInConnector) { cp.OrderInConnector++; } } this.Points.Insert(connectorPoint.OrderInConnector, connectorPoint); InvokePointsCountChanged(); this.InvalidateGeometry(); return(connectorPoint); }
public Rect GetBounds() { return(GeometryHelper.GetBasicControlBounds(this)); }
public void Connect(Node node1, Node node2) { if (StartNode != null) { StartNode.Connectors.Remove(this); } if (EndNode != null) { EndNode.Connectors.Remove(this); } StartNode = node1; EndNode = node2; Point[] optimalConnection; if (node1 != node2) { optimalConnection = GeometryHelper.ComputeOptimalConnection(node1, node2); } else { optimalConnection = GeometryHelper.ComputePointsForSelfAssociation(node1.GetBounds()); } #if SILVERLIGHT if (node1.GetBounds().Width == 0) { sourceMeasureValid = false; } if (node2.GetBounds().Width == 0) { targetMeasureValid = false; } #endif ConnectorPoint startPoint = new ConnectorPoint(ExolutioCanvas) { Placement = EPlacementKind.ParentAutoPos, ParentControl = node1, Connector = this, OrderInConnector = 0 }; ConnectorPoint endPoint = new ConnectorPoint(ExolutioCanvas) { Placement = EPlacementKind.ParentAutoPos, ParentControl = node2, Connector = this, OrderInConnector = 1 }; startPoint.SetPreferedPosition(optimalConnection.First()); endPoint.SetPreferedPosition(optimalConnection.Last()); foreach (ConnectorPoint point in Points) { if (point.OrderInConnector == 0) { point.ParentControl.InnerConnectorControl.Children.Remove(point); } else if (point.OrderInConnector == Points.Count - 1) { point.ParentControl.InnerConnectorControl.Children.Remove(point); } else { ExolutioCanvas.Children.Remove(point); } } points.Clear(); points.Add(startPoint); points.Add(endPoint); StartNode.InnerConnectorControl.Children.Add(startPoint); EndNode.InnerConnectorControl.Children.Add(endPoint); StartNode.Connectors.Add(this); // in the case where StartNode == EndNode, the connector is added only once EndNode.Connectors.AddIfNotContained(this); for (int i = (optimalConnection.Count() - 1) - 1; i >= 1; i--) { ConnectorPoint newPoint = BreakAtPoint(optimalConnection[i]); if (node1 == node2) { newPoint.Placement = EPlacementKind.RelativeCanvas; newPoint.SnapTo(node1, false); } } InvalidateGeometry(); }
/// <summary> /// Adjusts the end points position to an optimal position /// (when their <see cref="DragThumb.Placement"/> is set /// to <see cref="EPlacementKind.ParentAutoPos"/>). /// </summary> public bool AdjustEndPoints() { #if SILVERLIGHT if (StartNode != null && !sourceMeasureValid) { sourceMeasureValid = StartNode.GetBounds().Width != 0; } if (EndNode != null && !targetMeasureValid) { targetMeasureValid = EndNode.GetBounds().Width != 0; } #endif // StartNode and EndNode now can be null to allow disconnected connector points if (StartNode != null && !StartNode.IsMeasureValid) { return(false); } if (EndNode != null && !EndNode.IsMeasureValid) { return(false); } if (StartPoint == null || EndPoint == null || !targetMeasureValid || !sourceMeasureValid) { return(false); } #region set source junctionEnd position double angle = StartNode != null ? StartNode.BoundsAngle : 0; if (StartPoint.Placement == EPlacementKind.AbsoluteSubCanvas) { Point snappedStart = StartNode.GetBounds().Normalize().SnapPointToRectangle(StartPoint.Position); if (snappedStart != StartPoint.Position) { StartPoint.SetPreferedPosition(snappedStart); } } if (AutoPosModeOnly && StartPoint.Placement != EPlacementKind.ParentAutoPos) { StartPoint.Placement = EPlacementKind.ParentAutoPos; } // Condition removed to allow disconnected connector points //if (StartNode.IsMeasureValid /*&& (viewHelperPointsCollection == null || Points.Count == viewHelperPointsCollection.Count)*/ // /*&& (StartPoint.Placement == EPlacementKind.ParentAutoPos || viewHelperPointsCollection == null || viewHelperPointsCollection.PointsInvalid)*/) { Rect r1 = GeometryHelper.GetFirstElementBounds(this); Rect r2 = GeometryHelper.GetFirstButOneElementBounds(this); Point p1 = GeometryHelper.RectangleRectangleCenterIntersection(r1, r2, true, angle); if (StartPoint.Placement != EPlacementKind.ParentAutoPos && StartPoint.Position.AlmostEqual(p1) && !((IDraggable)StartPoint).DragThumb.IsDragged) { StartPoint.Placement = EPlacementKind.ParentAutoPos; } if (StartPoint.Placement == EPlacementKind.ParentAutoPos) { // simplified to this.. StartPoint.SetPreferedPosition(p1); } //if (viewHelperPointsCollection == null) //{ // StartPoint.SetPreferedPosition(p1); //} //else if (!viewHelperPointsCollection.First().AlmostEqual(p1)) //{ // if (viewHelperPointsCollection.PointsInvalid) // { // viewHelperPointsCollection[0].Set(p1); // StartPoint.SetPreferedPosition(p1); // viewHelperPointsCollection.PointsInvalid = false; // } // else // { // if (!sourceMeasureValid) // { // if (p1 != StartPoint.Position) // { // if (!AutoPosModeOnly) // { // StartPoint.Placement = EPlacementKind.AbsoluteSubCanvas; // Point snapped = r1.Normalize().SnapPointToRectangle(StartPoint.Position); // if (snapped != StartPoint.Position) // StartPoint.SetPreferedPosition(snapped); // } // } // } // else // { // viewHelperPointsCollection[0].Set(p1); // StartPoint.SetPreferedPosition(p1); // } // } //} //else //{ // StartPoint.SetPreferedPosition(p1); // StartPoint.Placement = EPlacementKind.ParentAutoPos; //} sourceMeasureValid = true; } #endregion #region set end junctionEnd position if (EndPoint.Placement == EPlacementKind.AbsoluteSubCanvas) { Point snappedEnd = EndNode.GetBounds().Normalize().SnapPointToRectangle(EndPoint.Position); if (snappedEnd != EndPoint.Position) { EndPoint.SetPreferedPosition(snappedEnd); } } angle = EndNode != null ? EndNode.BoundsAngle : 0; if (AutoPosModeOnly && EndPoint.Placement != EPlacementKind.ParentAutoPos) { EndPoint.Placement = EPlacementKind.ParentAutoPos; } // Condition removed to allow disconnected connector points //if (EndNode.IsMeasureValid /*&& (viewHelperPointsCollection == null || Points.Count == viewHelperPointsCollection.Count)*/ // /*&& (EndPoint.Placement == EPlacementKind.ParentAutoPos || viewHelperPointsCollection == null || viewHelperPointsCollection.PointsInvalid)*/) { Rect r1 = GeometryHelper.GetLastElementBounds(this); Rect r2 = GeometryHelper.GetLastButOneElementBounds(this); Point p2 = GeometryHelper.RectangleRectangleCenterIntersection(r1, r2, true, angle); if (EndPoint.Placement != EPlacementKind.ParentAutoPos && EndPoint.Position.AlmostEqual(p2) && !((IDraggable)EndPoint).DragThumb.IsDragged) { EndPoint.Placement = EPlacementKind.ParentAutoPos; } if (EndPoint.Placement == EPlacementKind.ParentAutoPos) { // simplified to this.. EndPoint.SetPreferedPosition(p2); } //if (viewHelperPointsCollection == null) //{ // EndPoint.SetPreferedPosition(p2); //} //else if (!viewHelperPointsCollection.Last().AlmostEqual(p2)) //{ // if (viewHelperPointsCollection.PointsInvalid) // { // viewHelperPointsCollection.Last().Set(p2); // EndPoint.SetPreferedPosition(p2); // viewHelperPointsCollection.PointsInvalid = false; // } // else // { // if (!targetMeasureValid) // { // if (p2 != EndPoint.Position) // { // EndPoint.Placement = EPlacementKind.AbsoluteSubCanvas; // Point snapped = r1.Normalize().SnapPointToRectangle(EndPoint.Position); // if (snapped != EndPoint.Position) // EndPoint.SetPreferedPosition(snapped); // } // } // else // { // viewHelperPointsCollection.Last().Set(p2); // EndPoint.SetPreferedPosition(p2); // } // } //} //else //{ // EndPoint.SetPreferedPosition(p2); // EndPoint.Placement = EPlacementKind.ParentAutoPos; //} targetMeasureValid = true; } #endregion return(true); }
public void InvalidateGeometry( ) { bool valid = AdjustEndPoints(); if (!valid) { return; } Point startPointShifted = StartPoint.CanvasPosition; Point endPointShifted = EndPoint.CanvasPosition; PathGeometry path = new PathGeometry(); PathFigure startFigure = null; PathFigure endFigure = null; #region define startFigure if (StartCapStyle != EConnectorCapStyle.Straight) { Point start = StartPoint.CanvasPosition; Point end = Points[1].CanvasPosition; startFigure = new PathFigure { StartPoint = start }; PolyLineSegment seg = new PolyLineSegment(); seg.Points.Add(end); startFigure.Segments.Add(seg); switch (StartCapStyle) { case EConnectorCapStyle.FullArrow: case EConnectorCapStyle.Arrow: case EConnectorCapStyle.Triangle: Point dummy = new Point(); if (StartCapStyle == EConnectorCapStyle.Arrow) { startFigure = GeometryHelper.CalculateArrow(startFigure, end, start, StartCapStyle != EConnectorCapStyle.Arrow, ref dummy); } else { startFigure = GeometryHelper.CalculateArrow(startFigure, end, start, StartCapStyle != EConnectorCapStyle.Arrow, ref endPointShifted); } break; case EConnectorCapStyle.FullDiamond: case EConnectorCapStyle.Diamond: startFigure = GeometryHelper.CalculateDiamond(startFigure, end, start, ref startPointShifted); break; } } #endregion #region define endFigure #if SILVERLIGHT #else if (EndCapStyle != EConnectorCapStyle.Straight) { endFigure = new PathFigure(); Point start = EndPoint.CanvasPosition; Point end = Points[Points.Count - 2].CanvasPosition; PolyLineSegment seg = new PolyLineSegment(); seg.Points.Add(end); endFigure.Segments.Add(seg); switch (EndCapStyle) { case EConnectorCapStyle.Arrow: case EConnectorCapStyle.FullArrow: case EConnectorCapStyle.Triangle: Point dummy = new Point(); if (EndCapStyle == EConnectorCapStyle.Arrow) { endFigure = GeometryHelper.CalculateArrow(endFigure, end, start, EndCapStyle != EConnectorCapStyle.Arrow, ref dummy); } else { endFigure = GeometryHelper.CalculateArrow(endFigure, end, start, EndCapStyle != EConnectorCapStyle.Arrow, ref endPointShifted); } break; case EConnectorCapStyle.Diamond: case EConnectorCapStyle.FullDiamond: endFigure = GeometryHelper.CalculateDiamond(endFigure, end, start, ref endPointShifted); break; } } #endif #endregion #region create junctionFigure if (StartCapStyle == EConnectorCapStyle.FullArrow || StartCapStyle == EConnectorCapStyle.FullDiamond || EndCapStyle == EConnectorCapStyle.FullDiamond || EndCapStyle == EConnectorCapStyle.FullArrow) { Fill = Brushes.Black; } else { Fill = Brushes.White; } PathFigure junctionFigure = new PathFigure { StartPoint = startPointShifted }; PolyLineSegment segment = new PolyLineSegment(); for (int i = 1; i < Points.Count - 1; i++) { segment.Points.Add(Points[i].CanvasPosition); } segment.Points.Add(endPointShifted); #if SILVERLIGHT #else segment.IsSmoothJoin = true; #endif junctionFigure.Segments.Add(segment); junctionFigure.IsFilled = false; #endregion if (startFigure != null) { path.Figures.Add(startFigure); } path.Figures.Add(junctionFigure); if (endFigure != null) { path.Figures.Add(endFigure); } path.FillRule = FillRule.Nonzero; geometry = path; InvalidateVisual(); VirtualReferentialThumb.CanvasPosition = GetVirtualCenterPosition(); //if (Association != null) //{ // Association.UpdateNameLabelPosition(); //} }