/// <summary> /// Initializes dragging of a line segment. /// </summary> /// <seealso cref="AutoPosModeOnly"/> /// <param name="e">The <see cref="T:System.Windows.Input.MouseButtonEventArgs"/> that contains the event data. This event data reports details about the mouse button that was pressed and the handled state.</param> protected override void OnMouseDown(MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left && !AutoPosModeOnly) { segmentDragging = true; dragLast = e.GetPosition(XCaseCanvas); int i = JunctionGeometryHelper.FindHitSegmentIndex(dragLast, Points); affectedPoints = new JunctionPoint[] { Points[i], Points[i + 1] }; startPositions = new Dictionary <DragThumb, rPoint>(); if (affectedPoints[0].Movable) { startPositions[affectedPoints[0]] = new rPoint(affectedPoints[0].Position) { tag = affectedPoints[0].Placement } } ; if (affectedPoints[1].Movable) { startPositions[affectedPoints[1]] = new rPoint(affectedPoints[1].Position) { tag = affectedPoints[1].Placement } } ; this.CaptureMouse(); } base.OnMouseDown(e); }
/// <summary> /// Creates new instance of <see cref="PSM_ComponentConnector" />. /// </summary> public PSM_ComponentConnector(XCaseCanvas canvas, IConnectable parentControl, IConnectable childControl, ComponentConnectorViewHelper viewHelper) { ParentControl = parentControl; ChildControl = childControl; XCaseCanvas = canvas; ViewHelper = viewHelper; if (viewHelper.Points.Count < 2) { viewHelper.Points.Clear(); viewHelper.Points.AppendRange(JunctionGeometryHelper.ComputeOptimalConnection(parentControl, childControl)); viewHelper.Points.PointsInvalid = true; } Junction = new XCaseJunction(canvas, viewHelper.Points); Junction.AutoPosModeOnly = true; XCaseCanvas.Children.Add(Junction); Junction.NewConnection(parentControl, null, childControl, null, viewHelper.Points); if (childControl is System.Windows.Controls.Control) { if (childControl is PSM_ContentContainer) { Junction.ContextMenu = ((PSM_ContentContainer)childControl).ContextMenu; } Junction.ContextMenu = ((System.Windows.Controls.Control)childControl).ContextMenu; } }
/// <summary> /// Initializes a view representation of a model element /// </summary> /// <param name="modelElement">Element to be represented</param> /// <param name="viewHelper">Element's viewHelper</param> /// <param name="controller">Element's controller</param> public override void InitializeRepresentant(Element modelElement, ViewHelper viewHelper, ElementController controller) { PIM_Association associationRepresentant = new PIM_Association(XCaseCanvas); associationRepresentant.InitializeRepresentant(modelElement, ((AssociationClassViewHelper)viewHelper).AssociationViewHelper, new AssociationController((Association)modelElement, controller.DiagramController)); Association = associationRepresentant; Association.AssociationClass = this; Association.AssociationName = null; Association.ViewHelper.MainLabelViewHelper.LabelVisible = false; AssociationClassViewHelper _viewHelper = (AssociationClassViewHelper)viewHelper; if (double.IsNaN(_viewHelper.X) || double.IsNaN(_viewHelper.Y)) { Rect r = RectExtensions.GetEncompassingRectangle(associationRepresentant.participantElements.Values); if (associationRepresentant.participantElements.Count > 2) { _viewHelper.X = r.GetCenter().X + 30; _viewHelper.Y = r.GetCenter().Y; } else { _viewHelper.X = r.GetCenter().X; _viewHelper.Y = r.GetCenter().Y + 20; } } base.InitializeRepresentant(modelElement, viewHelper, controller); if (associationRepresentant.ViewHelper.UseDiamond) { if (((AssociationClassViewHelper)ViewHelper).Points.Count == 0) { ((AssociationClassViewHelper)ViewHelper).Points.AppendRange( JunctionGeometryHelper.ComputeOptimalConnection(this, associationRepresentant.Diamond)); ((AssociationClassViewHelper)ViewHelper).Points.PointsInvalid = true; } junction = new XCaseJunction(XCaseCanvas, ((AssociationClassViewHelper)ViewHelper).Points) { Pen = MediaLibrary.DashedBlackPen }; XCaseCanvas.Children.Add(junction); junction.NewConnection(this, null, Association.Diamond, null, ((AssociationClassViewHelper)ViewHelper).Points); junction.SelectionOwner = this; } else { primitiveJunction = new XCasePrimitiveJunction(XCaseCanvas, this, Association) { Pen = MediaLibrary.DashedBlackPen }; } this.StartBindings(); }
/// <summary> /// Updates the connection when parent of <see cref="Association"/> changes. /// </summary> /// <param name="newParent">The new parent.</param> public void UpdateConnection(IConnectable newParent) { ParentRepresentation = newParent; ViewHelper.Points.Clear(); ViewHelper.Points.AppendRange(JunctionGeometryHelper.ComputeOptimalConnection(ParentRepresentation, ChildRepresentation)); if (!ChildRepresentation.IsMeasureValid || !ParentRepresentation.IsMeasureValid) { ViewHelper.Points.PointsInvalid = true; } Junction.NewConnection(ParentRepresentation, null, ChildRepresentation, null, ViewHelper.Points); }
void Source_LayoutUpdated(object sender, EventArgs e) { Rect bounds = SourceElement.GetBounds(); Point p = TargetElement.FindClosestPoint(bounds.GetCenter()); Point[] newPoints = JunctionGeometryHelper.ComputeOptimalConnection(bounds, new Rect(p.X, p.Y, 1, 1), false); if (newPoints[0] != points[0] || newPoints[1] != points[1]) { points = newPoints; InvalidateVisual(); } }
/// <summary> /// Initializes a view representation of a model element /// </summary> /// <param name="modelElement">Element to be represented</param> /// <param name="viewHelper">Element's viewHelper</param> /// <param name="controller">Element's controller</param> public void InitializeRepresentant(Element modelElement, ViewHelper viewHelper, ElementController controller) { Controller = (PSM_AssociationController)controller; ViewHelper = (PSMAssociationViewHelper)viewHelper; ParentRepresentation = (IConnectable)XCaseCanvas.ElementRepresentations[Association.Parent]; ChildRepresentation = (IConnectable)XCaseCanvas.ElementRepresentations[Association.Child]; if (Junction != null) { Junction.MouseEnter -= junction_MouseEnter; Junction.MouseLeave -= junction_MouseLeave; } if (ViewHelper.Points.Count < 2) { ViewHelper.Points.Clear(); ViewHelper.Points.AppendRange(JunctionGeometryHelper.ComputeOptimalConnection(ParentRepresentation, ChildRepresentation)); if (!ChildRepresentation.IsMeasureValid || !ParentRepresentation.IsMeasureValid) { ViewHelper.Points.PointsInvalid = true; } } remove = new ContextMenuItem("Remove subtree"); remove.Icon = ContextMenuIcon.GetContextIcon("delete2"); remove.Click += delegate { Controller.Remove(); }; cutToRoot = new ContextMenuItem("Cut association (add child as new root)"); cutToRoot.Click += delegate { Controller.CutToRoot(); }; Junction = new XCaseJunction(XCaseCanvas, ViewHelper.Points); Junction.PSM_Association = this; Junction.AutoPosModeOnly = true; Junction.SelectionOwner = this; Junction.NewConnection(ParentRepresentation, null, ChildRepresentation, null, ViewHelper.Points); Junction.Points[1].PositionChanged += AdjustLabelsPositions; XCaseCanvas.Children.Add(Junction); Junction.EndCapStyle = EJunctionCapStyle.Arrow; ((PSMElementViewBase)ChildRepresentation).Connector = this; this.StartBindings(); Association.PropertyChanged += ModelPropertyChanged; if (Junction != null) { Junction.MouseEnter += junction_MouseEnter; Junction.MouseLeave += junction_MouseLeave; } }
/// <summary> /// Initializes a view representation of a model element /// </summary> /// <param name="modelElement">Element to be represented</param> /// <param name="viewHelper">Element's viewHelper</param> /// <param name="controller">Element's controller</param> public void InitializeRepresentant(Element modelElement, ViewHelper viewHelper, ElementController controller) { XCaseCanvas.Children.Add(this); Controller = (CommentController)controller; ViewHelper = (CommentViewHelper)viewHelper; /* CommentText must be assigned now :( because it defines comment dimension * which have to be known before initializing the junction */ this.CommentText = ((Comment)modelElement).Body; if (ModelComment.AnnotatedElement != null && !(ModelComment.AnnotatedElement is Package)) { X = ViewHelper.X; Y = ViewHelper.Y; UpdateLayout(); if (XCaseCanvas.ElementRepresentations[ModelComment.AnnotatedElement] is DragThumb) { SnapTo((DragThumb)XCaseCanvas.ElementRepresentations[ModelComment.AnnotatedElement], false); } object target = XCaseCanvas.ElementRepresentations[ModelComment.AnnotatedElement]; if (target is PIM_Association && ((PIM_Association)target).ViewHelper.UseDiamond) { target = ((PIM_Association)target).Diamond; } if (target is IConnectable) { if (ViewHelper.LinePoints.Count == 0) { ViewHelper.LinePoints.AppendRange(JunctionGeometryHelper.ComputeOptimalConnection(this, (IConnectable)target)); } junction = new XCaseJunction(XCaseCanvas, ViewHelper.LinePoints) { Pen = MediaLibrary.DashedBlackPen }; XCaseCanvas.Children.Add(junction); junction.NewConnection(this, null, (IConnectable)target, null, ViewHelper.LinePoints); } else if (target is IPrimitiveJunctionTarget) { primitiveJunction = new XCasePrimitiveJunction(XCaseCanvas, this, (IPrimitiveJunctionTarget)target); } else { throw new ArgumentException("Commentary can be connected only to IConnectable or IPrimitiveJunctionTarget"); } } this.StartBindings(); }
public Point FindClosestPoint(Point point) { if (simpleAssociationJunction != null) { return(JunctionGeometryHelper.FindClosestPoint(simpleAssociationJunction, point)); } else if (Diamond != null) { return(Diamond.GetBounds().GetCenter()); } else { return(GetBounds().GetCenter()); } }
/// <summary> /// Returns context menu items. /// </summary> /// <returns></returns> internal IEnumerable <ContextMenuItem> GeneralizationMenuItems() { ContextMenuItem addCommentary = new ContextMenuItem("Add commentary"); addCommentary.Click += delegate { NewModelCommentToDiagramCommand command = (NewModelCommentToDiagramCommand)CommandFactoryBase <NewModelCommentaryToDiagramCommandFactory> .Factory().Create(Controller.DiagramController); command.AnnotatedElement = Generalization; Point p = JunctionGeometryHelper.FindClosestPoint(GeneralizationJunction, GeneralizationJunction.GetBounds().GetCenter()); command.X = p.X + 20; command.Y = p.Y + 20; command.Set(Controller.DiagramController.ModelController, null); command.Execute(); }; return(new ContextMenuItem[] { addCommentary }); }
/// <summary> /// Dragging beggins, the <paramref name="item"/> will be the source of the connection. /// </summary> /// <param name="item">item clicked</param> /// <param name="e">event arguments</param> public override void SelectableItemPreviewMouseDown(ISelectable item, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Right) { Canvas.State = ECanvasState.Normal; e.Handled = true; return; } base.SelectableItemPreviewMouseDown(item, e); if (item is IConnectable && e.ChangedButton == MouseButton.Left) { Canvas.CaptureMouse(); foreach (ISelectable i in Canvas.SelectedItems) { i.IsSelected = false; } Canvas.SelectedItems.Clear(); draggedPoint = new JunctionPoint(Canvas) { Width = 0, Height = 0 }; Canvas.Children.Add(draggedPoint); draggedPoint.SetPreferedPosition(e.GetPosition(Canvas)); SetZIndex(draggedPoint, -5); draggedPoint.Visibility = Visibility.Visible; //throw new NotImplementedException("Method or operation is not implemented."); draggedConnection = new XCaseJunction(Canvas); draggedPoint.Junction = draggedConnection; (item as IConnectable).Highlight(); InConnectionDrag = true; draggedConnection.DragConnection(item as IConnectable, draggedPoint, Canvas); Canvas.Children.Add(draggedConnection); draggedConnection.EndCapStyle = JunctionGeometryHelper.GetCap(DraggedConnectionType); e.Handled = true; draggedConnection.InvalidateGeometry(); ConnectableItemMouseEnter((IConnectable)item); } }
/// <summary> /// Returns context menu items for junction. /// </summary> /// <returns></returns> internal IEnumerable <ContextMenuItem> JunctionMenuItems() { if (!AutoPosModeOnly) { ContextMenuItem breakCommand = new ContextMenuItem("Break line here"); breakCommand.Click += delegate { ViewController.BreakLine(downPos, JunctionGeometryHelper.FindHitSegmentIndex(downPos, Points) + 1, viewHelperPointsCollection, XCaseCanvas.Controller); }; ContextMenuItem autoPosEndsCommand = new ContextMenuItem("Line ends auto-position"); autoPosEndsCommand.Click += delegate { StartPoint.Placement = EPlacementKind.ParentAutoPos; EndPoint.Placement = EPlacementKind.ParentAutoPos; InvalidateGeometry(); }; if (this.Association != null) { ContextMenuItem removeEndCommand = new ContextMenuItem("Remove from association"); removeEndCommand.Click += delegate { Association.Controller.RemoveAssociationEnd(this.AssociationEnd.AssociationEnd); }; return(new[] { breakCommand, autoPosEndsCommand, removeEndCommand }); } return(new[] { breakCommand, autoPosEndsCommand }); } else { return(new ContextMenuItem[0]); } }
/// <summary> /// Initializes the control properties from view helper (especially points are restored). /// </summary> private void InitializeFromViewHelper() { IConnectable sourceElement = (IConnectable)XCaseCanvas.ElementRepresentations[Controller.Generalization.Specific]; IConnectable targetElement = (IConnectable)XCaseCanvas.ElementRepresentations[Controller.Generalization.General]; if (ViewHelper.Points.Count == 0) { ViewHelper.Points.AppendRange(JunctionGeometryHelper.ComputeOptimalConnection(sourceElement, targetElement)); } if (GeneralizationJunction != null) { GeneralizationJunction.DeleteFromCanvas(); } GeneralizationJunction = new XCaseJunction(XCaseCanvas, this, ViewHelper.Points); if (sourceElement is PSM_Class || targetElement is PSM_Class) { GeneralizationJunction.AutoPosModeOnly = true; } GeneralizationJunction.NewConnection(sourceElement, null, targetElement, null, ViewHelper.Points); XCaseCanvas.Children.Add(GeneralizationJunction); GeneralizationJunction.StartCapStyle = EJunctionCapStyle.Straight; GeneralizationJunction.EndCapStyle = EJunctionCapStyle.Triangle; }
private void InitializeFromViewHelper() { if (ViewHelper.AssociationEndsViewHelpers.Count != Association.Ends.Count) { ViewHelper.CreateEndsViewHelpers(this.Association); } if (ViewHelper.ForceUseDiamond) { ViewHelper.UseDiamond = true; } ViewHelper.ForceUseDiamond = false; participantElements = new Dictionary <AssociationEndViewHelper, IConnectable>(); foreach (AssociationEndViewHelper endViewHelper in ViewHelper.AssociationEndsViewHelpers) { if (!(XCaseCanvas.ElementRepresentations[endViewHelper.AssociationEnd.Class] is IConnectable)) { throw new InvalidOperationException("One of the association ends is not visualized as IConnectable"); } participantElements[endViewHelper] = XCaseCanvas.ElementRepresentations[endViewHelper.AssociationEnd.Class] as IConnectable; } foreach (Control c in subControls) { if (c != null) { c.MouseEnter -= junction_MouseEnter; c.MouseLeave -= junction_MouseLeave; } } if (ViewHelper.UseDiamond) { // simpleAssociationJunction field won't be used if diamond is used if (simpleAssociationJunction != null) { simpleAssociationJunction.DeleteFromCanvas(); ViewHelper.AssociationEndsViewHelpers[0].Points.Clear(); } // prepare the diamond if (Diamond == null) { Diamond = new AssociationDiamond(XCaseCanvas, this, ViewHelper); XCaseCanvas.Children.Add(Diamond); } Rect r = RectExtensions.GetEncompassingRectangle(participantElements.Values); if (ViewHelper.X == 0 && ViewHelper.Y == 0) { Diamond.X = r.GetCenter().X - Diamond.ActualWidth / 2; Diamond.Y = r.GetCenter().Y - Diamond.ActualHeight / 2; ViewHelper.X = Diamond.X; ViewHelper.Y = Diamond.Y; } Diamond.UpdateLayout(); /* * for each association end there will be one junction between the diamond and the * participating element. Start point of the junction will lay on the diamond, end * point of the junction will lay on the participating element and will be bound to * an association end. */ foreach (AssociationEndViewHelper endViewHelper in ViewHelper.AssociationEndsViewHelpers) { //compute the start and end point of each junction if they are not already computed if (endViewHelper.Points.Count < 2) { endViewHelper.Points.Clear(); endViewHelper.Points.AppendRange(JunctionGeometryHelper.ComputeOptimalConnection(Diamond, participantElements[endViewHelper])); if (!Diamond.IsMeasureValid || !participantElements[endViewHelper].IsMeasureValid) { endViewHelper.Points.PointsInvalid = true; } } XCaseJunction junction = new XCaseJunction(XCaseCanvas, this, endViewHelper.Points); junction.NewConnection(Diamond, null, participantElements[endViewHelper], endViewHelper, endViewHelper.Points); junction.StartPoint.Movable = false; junction.StartPoint.Visibility = Visibility.Hidden; associationJunctions[endViewHelper.AssociationEnd] = junction; XCaseCanvas.Children.Add(junction); } } else { foreach (XCaseJunction junction in associationJunctions.Values) { junction.DeleteFromCanvas(); } if (Diamond != null) { Diamond.DeleteFromCanvas(); Diamond = null; } associationJunctions.Clear(); IConnectable SourceElement = (IConnectable)XCaseCanvas.ElementRepresentations[ViewHelper.AssociationEndsViewHelpers[0].AssociationEnd.Class]; IConnectable TargetElement; if (ViewHelper.AssociationEndsViewHelpers.Count == 2 && ViewHelper.AssociationEndsViewHelpers[0].AssociationEnd.Class == ViewHelper.AssociationEndsViewHelpers[1].AssociationEnd.Class) { TargetElement = SourceElement; if (ViewHelper.Points.Count == 0) { ViewHelper.Points.AppendRange(JunctionGeometryHelper.ComputePointsForSelfAssociation(SourceElement.GetBounds())); if (!SourceElement.IsMeasureValid) { ViewHelper.Points.PointsInvalid = true; } } } /* * two different classes are connected directly without using central diamond, * association will consist of two points * in optimal position to connect two rectangles. */ else if (ViewHelper.AssociationEndsViewHelpers.Count == 2) { TargetElement = (IConnectable)XCaseCanvas.ElementRepresentations[ViewHelper.AssociationEndsViewHelpers[1].AssociationEnd.Class]; if (ViewHelper.Points.Count < 2) { ViewHelper.Points.Clear(); ViewHelper.Points.AppendRange(JunctionGeometryHelper.ComputeOptimalConnection(SourceElement, TargetElement)); if (!SourceElement.IsMeasureValid) { ViewHelper.Points.PointsInvalid = true; } } } else { throw new InvalidOperationException("UseDiamond must be true if there are more association ends than 2"); } /* * diamond is not used, simpleAssociationJunction field will be used to * represent the junction */ if (simpleAssociationJunction != null) { simpleAssociationJunction.DeleteFromCanvas(); } simpleAssociationJunction = new XCaseJunction(XCaseCanvas, this, ViewHelper.Points); if (Association.Ends.Count == 1) { simpleAssociationJunction.NewConnection(SourceElement, null, TargetElement, ViewHelper.AssociationEndsViewHelpers[0], ViewHelper.Points); } else { simpleAssociationJunction.NewConnection(SourceElement, ViewHelper.AssociationEndsViewHelpers[0], TargetElement, ViewHelper.AssociationEndsViewHelpers[1], ViewHelper.Points); } XCaseCanvas.Children.Add(simpleAssociationJunction); } foreach (Control c in subControls) { if (c != null) { c.MouseEnter += junction_MouseEnter; c.MouseLeave += junction_MouseLeave; } } }
public Point FindClosestPoint(Point point) { return(JunctionGeometryHelper.FindClosestPoint(this, point)); }
/// <summary> /// Recreates the junction's geometry and causes it to redraw. /// </summary> public void InvalidateGeometry() { AdjustEndPoints(); PathGeometry path = new PathGeometry(); PathFigure startFigure = null; PathFigure endFigure = null; Point startPointShifted = StartPoint.CanvasPosition; Point endPointShifted = EndPoint.CanvasPosition; #region define startFigure if (StartCapStyle != EJunctionCapStyle.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 EJunctionCapStyle.FullArrow: case EJunctionCapStyle.Arrow: case EJunctionCapStyle.Triangle: Point dummy = new Point(); if (StartCapStyle == EJunctionCapStyle.Arrow) { startFigure = JunctionGeometryHelper.CalculateArrow(startFigure, end, start, StartCapStyle != EJunctionCapStyle.Arrow, ref dummy); } else { startFigure = JunctionGeometryHelper.CalculateArrow(startFigure, end, start, StartCapStyle != EJunctionCapStyle.Arrow, ref startPointShifted); } break; case EJunctionCapStyle.FullDiamond: case EJunctionCapStyle.Diamond: startFigure = JunctionGeometryHelper.CalculateDiamond(startFigure, end, start, ref startPointShifted); break; } } #endregion #region define endFigure if (EndCapStyle != EJunctionCapStyle.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 EJunctionCapStyle.Arrow: case EJunctionCapStyle.FullArrow: case EJunctionCapStyle.Triangle: Point dummy = new Point(); if (StartCapStyle == EJunctionCapStyle.Arrow) { endFigure = JunctionGeometryHelper.CalculateArrow(endFigure, end, start, EndCapStyle != EJunctionCapStyle.Arrow, ref dummy); } else { endFigure = JunctionGeometryHelper.CalculateArrow(endFigure, end, start, EndCapStyle != EJunctionCapStyle.Arrow, ref endPointShifted); } break; case EJunctionCapStyle.Diamond: case EJunctionCapStyle.FullDiamond: endFigure = JunctionGeometryHelper.CalculateDiamond(endFigure, end, start, ref endPointShifted); break; } } #endregion #region create junctionFigure 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); segment.IsSmoothJoin = true; junctionFigure.Segments.Add(segment); junctionFigure.IsFilled = false; #endregion if (startFigure != null) { path.Figures.Add(startFigure); } if (endFigure != null) { path.Figures.Add(endFigure); } path.FillRule = FillRule.Nonzero; path.Figures.Add(junctionFigure); geometry = path; InvalidateVisual(); if (Association != null) { Association.UpdateNameLabelPosition(); } }
/// <summary> /// Finds the closest point. /// </summary> /// <param name="point">The point.</param> /// <returns></returns> public Point FindClosestPoint(Point point) { return(JunctionGeometryHelper.FindClosestPoint(GeneralizationJunction, point)); }
/// <summary> /// Finds the closest point. /// </summary> /// <param name="point">The point.</param> /// <returns></returns> Point IPrimitiveJunctionTarget.FindClosestPoint(Point point) { return(JunctionGeometryHelper.FindClosestPoint(Junction, point)); }
/// <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 void AdjustEndPoints() { #region set source junctionEnd position double angle = SourceElement != null ? ((IConnectable)SourceElement).BoundsAngle : 0; if (AutoPosModeOnly && StartPoint.Placement != EPlacementKind.ParentAutoPos) { StartPoint.Placement = EPlacementKind.ParentAutoPos; } if (SourceElement != null && SourceElement.IsMeasureValid && (viewHelperPointsCollection == null || Points.Count == viewHelperPointsCollection.Count) && (StartPoint.Placement == EPlacementKind.ParentAutoPos || viewHelperPointsCollection == null || viewHelperPointsCollection.PointsInvalid)) { Rect r1 = JunctionGeometryHelper.GetFirstElementBounds(this); Rect r2 = JunctionGeometryHelper.GetFirstButOneElementBounds(this); Point p1 = JunctionGeometryHelper.RectangleRectangleCenterIntersection(r1, r2, true, angle); 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 angle = TargetElement != null ? ((IConnectable)TargetElement).BoundsAngle : 0; if (AutoPosModeOnly && EndPoint.Placement != EPlacementKind.ParentAutoPos) { EndPoint.Placement = EPlacementKind.ParentAutoPos; } if (TargetElement != null && TargetElement.IsMeasureValid && (viewHelperPointsCollection == null || Points.Count == viewHelperPointsCollection.Count) && (EndPoint.Placement == EPlacementKind.ParentAutoPos || viewHelperPointsCollection == null || viewHelperPointsCollection.PointsInvalid)) { Rect r1 = JunctionGeometryHelper.GetLastElementBounds(this); Rect r2 = JunctionGeometryHelper.GetLastButOneElementBounds(this); Point p2 = JunctionGeometryHelper.RectangleRectangleCenterIntersection(r1, r2, true, angle); 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 }