/// <summary> /// Gets the port placement based on the parent and child shapes bounds. /// </summary> /// <param name="parentShapeDimensions"></param> /// <param name="childShapeRelativeBounds"></param> /// <returns></returns> /// <remarks>Source: Dsl-Tools Diagrams</remarks> public static PortPlacement GetPortPlacement(RectangleD parentShapeDimensions, RectangleD childShapeRelativeBounds) { PointD pointD1 = new PointD(childShapeRelativeBounds.X + (childShapeRelativeBounds.Width / 2.0), childShapeRelativeBounds.Y + (childShapeRelativeBounds.Height / 2.0)); PointD pointD2 = new PointD(parentShapeDimensions.Width / 2.0, parentShapeDimensions.Height / 2.0); double d1 = System.Math.Atan2(pointD2.Y, pointD2.X); double d2 = System.Math.Atan2(pointD1.Y - pointD2.Y, pointD1.X - pointD2.X); if ((d2 <= d1) && (d2 >= -d1)) return PortPlacement.Right; if ((d2 > d1) && (d2 < (Math.PI - d1))) return PortPlacement.Bottom; if ((d2 > -(Math.PI - d1)) && (d2 < -d1)) return PortPlacement.Top; if ((d2 >= (Math.PI - d1)) || (d2 <= -(Math.PI - d1))) return PortPlacement.Left; throw new System.InvalidOperationException(); }
/// <summary> /// This function corrects the given proposed location if the given child shape is a relative shape and /// is only allowed to be placed on the edge of its parent. /// </summary> /// <param name="parentShape">Parent shape.</param> /// <param name="childShape">Child shape.</param> /// <param name="proposedLocation">Proposed location.</param> /// <remarks> /// This function needs to be called withing a modeling transaction. /// /// This function assigns new values to Location and PortPlacement if necessary. /// </remarks> /// <returns> /// Location that was assigned to the shape. It might have the same value as the location /// the shape had before calling this function. /// </returns> public static PointD CorrectPortLocation(NodeShape parentShape, NodeShape childShape, PointD proposedLocation) { if (parentShape == null) { throw new ArgumentNullException("parentShape"); } if (childShape == null) { throw new ArgumentNullException("childShape"); } if (!childShape.IsRelativeChildShape || childShape.MovementBehaviour != ShapeMovementBehaviour.PositionOnEdgeOfParent) { return(proposedLocation); } RectangleD rectParent = parentShape.Bounds; RectangleD proposedBounds = new RectangleD(proposedLocation, childShape.Size); PortPlacement placement = NodeShape.GetPortPlacement(rectParent, proposedBounds); return(CorrectPortLocation(placement, parentShape, childShape, proposedLocation)); }
/// <summary> /// Calculates a location based on the shape dimensions as well as the proposed location. /// </summary> /// <param name="shapeDimensions">Dimensions of the shape, this link start/end is created at.</param> /// <param name="proposedLocation">Proposed location of the link start/end.</param> /// <returns>Calculated location.</returns> public static PointD CalculateLocation(RectangleD shapeDimensions, PointD proposedLocation) { LinkPlacement placement = GetLinkPlacement(shapeDimensions, proposedLocation); return(CalculateLocation(placement, shapeDimensions, proposedLocation)); }
/// <summary> /// Calculates the link placement for start or end point. /// </summary> /// <param name="isStartPoint"></param> /// <returns></returns> private LinkPlacement GetLinkPlacement(bool isStartPoint) { RectangleD sourceBounds = this.SourceAnchor.FromShape.AbsoluteBounds; RectangleD targetBounds = this.TargetAnchor.ToShape.AbsoluteBounds; if (!isStartPoint) { sourceBounds = targetBounds; targetBounds = this.SourceAnchor.FromShape.AbsoluteBounds; } double horizontalDifference = Math.Abs(targetBounds.Left - sourceBounds.Left); double verticalDifference = Math.Abs(targetBounds.Top - sourceBounds.Top); if (sourceBounds.Left <= targetBounds.Left && sourceBounds.Top <= targetBounds.Top) { double horizontalDifferenceReal = targetBounds.Left - sourceBounds.Right; double verticalDifferenceReal = targetBounds.Top - sourceBounds.Bottom; if (horizontalDifferenceReal > 0 && verticalDifferenceReal > 0) { horizontalDifference = horizontalDifferenceReal; verticalDifference = verticalDifferenceReal; } if (horizontalDifference >= verticalDifference) { return(LinkPlacement.Right); } else { return(LinkPlacement.Bottom); } } else if (sourceBounds.Left <= targetBounds.Left && sourceBounds.Top > targetBounds.Top) { double horizontalDifferenceReal = targetBounds.Left - sourceBounds.Right; double verticalDifferenceReal = sourceBounds.Top - targetBounds.Bottom; if (horizontalDifferenceReal > 0 && verticalDifferenceReal > 0) { horizontalDifference = horizontalDifferenceReal; verticalDifference = verticalDifferenceReal; } if (horizontalDifference >= verticalDifference) { return(LinkPlacement.Right); } else { return(LinkPlacement.Top); } } else if (sourceBounds.Left > targetBounds.Left && sourceBounds.Top <= targetBounds.Top) { double horizontalDifferenceReal = sourceBounds.Left - targetBounds.Right; double verticalDifferenceReal = targetBounds.Top - sourceBounds.Bottom; if (horizontalDifferenceReal > 0 && verticalDifferenceReal > 0) { horizontalDifference = horizontalDifferenceReal; verticalDifference = verticalDifferenceReal; } if (horizontalDifference >= verticalDifference) { return(LinkPlacement.Left); } else { return(LinkPlacement.Bottom); } } else //if (sourceBounds.Left > targetBounds.Left && sourceBounds.Top > targetBounds.Top) { double horizontalDifferenceReal = sourceBounds.Left - targetBounds.Right; double verticalDifferenceReal = sourceBounds.Top - targetBounds.Bottom; if (horizontalDifferenceReal > 0 && verticalDifferenceReal > 0) { horizontalDifference = horizontalDifferenceReal; verticalDifference = verticalDifferenceReal; } if (horizontalDifference >= verticalDifference) { return(LinkPlacement.Left); } else { return(LinkPlacement.Top); } } }
static RectangleD() { RectangleD.Empty = new RectangleD(0.0, 0.0, 0.0, 0.0); }
/// <summary> /// Does this rectangle contain the specified rectangle? /// </summary> /// <param name="rectangle">Rectangle</param> /// <returns>True if the rectangle contains the specified rectangle. False otherwise.</returns> public bool Contains(RectangleD rectangle) { if ((X <= rectangle.X) && ((rectangle.X + rectangle.Width) <= (X + Width)) && (Y <= rectangle.Y)) return (rectangle.Y + rectangle.Height) <= (Y + Height); return false; }
/// <summary> /// This function corrects the given proposed location if the given child shape is a relative shape and /// is only allowed to be placed on the edge of its parent. /// </summary> /// <param name="parentShape">Parent shape.</param> /// <param name="childShape">Child shape.</param> /// <param name="proposedLocation">Proposed location.</param> /// <remarks> /// This function needs to be called withing a modeling transaction. /// /// This function assigns new values to Location and PortPlacement if necessary. /// </remarks> /// <returns> /// Location that was assigned to the shape. It might have the same value as the location /// the shape had before calling this function. /// </returns> public static PointD CorrectPortLocation(NodeShape parentShape, NodeShape childShape, PointD proposedLocation) { if (parentShape == null) throw new ArgumentNullException("parentShape"); if (childShape == null) throw new ArgumentNullException("childShape"); if (!childShape.IsRelativeChildShape || childShape.MovementBehaviour != ShapeMovementBehaviour.PositionOnEdgeOfParent) return proposedLocation; RectangleD rectParent = parentShape.Bounds; RectangleD proposedBounds = new RectangleD(proposedLocation, childShape.Size); PortPlacement placement = NodeShape.GetPortPlacement(rectParent, proposedBounds); return CorrectPortLocation(placement, parentShape, childShape, proposedLocation); }
/// <summary> /// Create relationship if possible. Release mouse afterwards. /// </summary> /// <param name="e"></param> protected override void OnMouseUp(MouseButtonEventArgs e) { if (hitItem != null) { object targetElement = hitItem.SelectedData; if (sourceItem != null && hitItem != null && this.diagramDesigner.CreateRelationshipCommand != null) { ViewModelRelationshipCreationInfo info = new ViewModelRelationshipCreationInfo(sourceItem.SelectedData, hitItem.SelectedData); // calcualte source and target points if (hitItem is FrameworkElement) { FrameworkElement sourceFElement = sourceConnector.DiagramItem; double sourceLeft = Canvas.GetLeft(sourceFElement); double sourceTop = Canvas.GetTop(sourceFElement); FrameworkElement targetFElement = hitItem as FrameworkElement; double targetLeft = Canvas.GetLeft(targetFElement); double targetTop = Canvas.GetTop(targetFElement); if (!double.IsNaN(sourceLeft) && !double.IsNaN(sourceTop) && !double.IsNaN(targetLeft) && !double.IsNaN(targetTop)) { Point proposedTarget = e.GetPosition(this.diagramDesigner); PointD proposedSourcePoint = new PointD(startPoint.X, startPoint.Y); PointD proposedTargetPoint = new PointD(proposedTarget.X, proposedTarget.Y); // calculate points //Point sourcePointT = sourceFElement.TranslatePoint(new Point(0, 0), this.diagramDesigner); //Point targetPointT = targetFElement.TranslatePoint(new Point(0, 0), this.diagramDesigner); Point sourcePoint = sourceFElement.TransformToAncestor(this.diagramDesigner).Transform(new Point(0, 0)); Point targetPoint = targetFElement.TransformToAncestor(this.diagramDesigner).Transform(new Point(0, 0)); // calculate side for source RectangleD sourceBounds = new RectangleD(sourcePoint.X, sourcePoint.Y, sourceFElement.Width, sourceFElement.Height); info.ProposedSourcePoint = LinkShape.CalculateLocation(sourceBounds, proposedSourcePoint); // calculate side for target RectangleD targeteBounds = new RectangleD(targetPoint.X, targetPoint.Y, targetFElement.Width, targetFElement.Height); info.ProposedTargetPoint = LinkShape.CalculateLocation(targeteBounds, proposedTargetPoint); } } this.diagramDesigner.CreateRelationshipCommand.Execute(info); } } if (this.IsMouseCaptured) this.ReleaseMouseCapture(); AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.diagramDesigner); if (adornerLayer != null) { adornerLayer.Remove(this); } }
/// <summary> /// This function corrects the given proposed location if the given child shape is a relative shape and /// is only allowed to be placed on the edge of its parent. /// </summary> /// <param name="placement">Proposed placement.</param> /// <param name="parentShape">Parent shape.</param> /// <param name="childShape">Child shape.</param> /// <param name="proposedLocation">Proposed location.</param> /// <remarks> /// This function needs to be called withing a modeling transaction. /// /// This function assigns new values to Location and PortPlacement if necessary. /// </remarks> /// <returns> /// Location that was assigned to the shape. It might have the same value as the location /// the shape had before calling this function. /// </returns> public static PointD CorrectPortLocation(PortPlacement placement, NodeShape parentShape, NodeShape childShape, PointD proposedLocation) { PointD newLocation = proposedLocation; RectangleD rectParent = parentShape.Bounds; switch (placement) { case PortPlacement.Left: newLocation.X = -childShape.Size.Width / 2.0; if (newLocation.Y < 0.0) { newLocation.Y = 0.0; } else if (newLocation.Y > (rectParent.Height - childShape.Size.Height)) { newLocation.Y = rectParent.Height - childShape.Size.Height; } break; case PortPlacement.Top: newLocation.Y = -childShape.Size.Height / 2.0; if (newLocation.X < 0.0) { newLocation.X = 0.0; } else if (newLocation.X > (rectParent.Width - childShape.Size.Width)) { newLocation.X = rectParent.Width - childShape.Size.Width; } break; case PortPlacement.Right: newLocation.X = rectParent.Width - (childShape.Size.Width / 2.0); if (newLocation.Y < 0.0) { newLocation.Y = 0.0; } else if (newLocation.Y > (rectParent.Height - childShape.Size.Height)) { newLocation.Y = rectParent.Height - childShape.Size.Height; } break; case PortPlacement.Bottom: newLocation.Y = rectParent.Height - (childShape.Size.Height / 2.0); if (newLocation.X < 0.0) { newLocation.X = 0.0; } else if (newLocation.X > (rectParent.Width - childShape.Size.Width)) { newLocation.X = rectParent.Width - childShape.Size.Width; } break; } if (childShape.Location != newLocation) { childShape.Location = newLocation; childShape.PlacementSide = placement; childShape.UpdateAbsoluteLocation(); } return(newLocation); }
/// <summary> /// Calculates a location based on the shape dimensions as well as the proposed location. /// </summary> /// <param name="placement">Link placement.</param> /// <param name="shapeDimensions">Dimensions of the shape, this link start/end is created at.</param> /// <param name="proposedLocation">Proposed location of the link start/end.</param> /// <returns>Calculated location.</returns> public static PointD CalculateLocation(LinkPlacement placement, RectangleD shapeDimensions, PointD proposedLocation) { double x = proposedLocation.X; double y = proposedLocation.Y; double itemWidth = 7; double itemHeight = 7; switch (placement) { case LinkPlacement.Left: x = shapeDimensions.Left - itemWidth; if (y <= (shapeDimensions.Top - itemHeight)) y = shapeDimensions.Top - itemHeight; else if (y > shapeDimensions.Bottom) y = shapeDimensions.Bottom; break; case LinkPlacement.Top: y = shapeDimensions.Top - itemHeight; if (x <= (shapeDimensions.Left - itemWidth)) x = shapeDimensions.Left - itemWidth; else if (x > shapeDimensions.Right) x = shapeDimensions.Right; break; case LinkPlacement.Right: x = shapeDimensions.Right + 3.4 * 2; if (y <= (shapeDimensions.Top - itemHeight)) y = shapeDimensions.Top - itemHeight; else if (y > shapeDimensions.Bottom) y = shapeDimensions.Bottom; break; case LinkPlacement.Bottom: y = shapeDimensions.Bottom + 3.4 * 2; if (x <= (shapeDimensions.Left - itemWidth)) x = shapeDimensions.Left - itemWidth; else if (x > shapeDimensions.Right) x = shapeDimensions.Right; break; } return new PointD(x, y); }
/// <summary> /// Calculates a location based on the shape dimensions as well as the proposed location. /// </summary> /// <param name="shapeDimensions">Dimensions of the shape, this link start/end is created at.</param> /// <param name="proposedLocation">Proposed location of the link start/end.</param> /// <returns>Calculated location.</returns> public static PointD CalculateLocation(RectangleD shapeDimensions, PointD proposedLocation) { LinkPlacement placement = GetLinkPlacement(shapeDimensions, proposedLocation); return CalculateLocation(placement, shapeDimensions, proposedLocation); }
/// <summary> /// Gets the link placement based on the shape dimensions as well as the proposed location. /// </summary> /// <param name="shapeDimensions">Dimensions of the shape, this link start/end is created at.</param> /// <param name="proposedLocation">Proposed location of the link start/end.</param> /// <returns>LinkPlacement.</returns> public static LinkPlacement GetLinkPlacement(RectangleD shapeDimensions, PointD proposedLocation) { PointD pointD1 = new PointD(proposedLocation.X + 3.5 - shapeDimensions.Left, proposedLocation.Y + 3.5 - shapeDimensions.Top); PointD pointD2 = new PointD(shapeDimensions.Width / 2.0, shapeDimensions.Height / 2.0); double d1 = System.Math.Atan2(pointD2.Y, pointD2.X); double d2 = System.Math.Atan2(pointD1.Y - pointD2.Y, pointD1.X - pointD2.X); if ((d2 <= d1) && (d2 >= -d1)) return LinkPlacement.Right; if ((d2 > d1) && (d2 < (Math.PI - d1))) return LinkPlacement.Bottom; if ((d2 > -(Math.PI - d1)) && (d2 < -d1)) return LinkPlacement.Top; if ((d2 >= (Math.PI - d1)) || (d2 <= -(Math.PI - d1))) return LinkPlacement.Left; throw new System.InvalidOperationException(); }
static RectangleD() { RectangleD.Empty = new RectangleD(0.0, 0.0, 0.0, 0.0); }
/// <summary> /// Calculates a location based on the shape dimensions as well as the proposed location. /// </summary> /// <param name="placement">Link placement.</param> /// <param name="shapeDimensions">Dimensions of the shape, this link start/end is created at.</param> /// <param name="proposedLocation">Proposed location of the link start/end.</param> /// <returns>Calculated location.</returns> public static PointD CalculateLocation(LinkPlacement placement, RectangleD shapeDimensions, PointD proposedLocation) { double x = proposedLocation.X; double y = proposedLocation.Y; double itemWidth = 7; double itemHeight = 7; switch (placement) { case LinkPlacement.Left: x = shapeDimensions.Left - itemWidth; if (y <= (shapeDimensions.Top - itemHeight)) { y = shapeDimensions.Top - itemHeight; } else if (y > shapeDimensions.Bottom) { y = shapeDimensions.Bottom; } break; case LinkPlacement.Top: y = shapeDimensions.Top - itemHeight; if (x <= (shapeDimensions.Left - itemWidth)) { x = shapeDimensions.Left - itemWidth; } else if (x > shapeDimensions.Right) { x = shapeDimensions.Right; } break; case LinkPlacement.Right: x = shapeDimensions.Right + 3.4 * 2; if (y <= (shapeDimensions.Top - itemHeight)) { y = shapeDimensions.Top - itemHeight; } else if (y > shapeDimensions.Bottom) { y = shapeDimensions.Bottom; } break; case LinkPlacement.Bottom: y = shapeDimensions.Bottom + 3.4 * 2; if (x <= (shapeDimensions.Left - itemWidth)) { x = shapeDimensions.Left - itemWidth; } else if (x > shapeDimensions.Right) { x = shapeDimensions.Right; } break; } return(new PointD(x, y)); }
/// <summary> /// Gets the port placement based on the parent and child shapes bounds. /// </summary> /// <param name="parentShapeDimensions"></param> /// <param name="childShapeRelativeBounds"></param> /// <returns></returns> /// <remarks>Source: Dsl-Tools Diagrams</remarks> public static PortPlacement GetPortPlacement(RectangleD parentShapeDimensions, RectangleD childShapeRelativeBounds) { PointD pointD1 = new PointD(childShapeRelativeBounds.X + (childShapeRelativeBounds.Width / 2.0), childShapeRelativeBounds.Y + (childShapeRelativeBounds.Height / 2.0)); PointD pointD2 = new PointD(parentShapeDimensions.Width / 2.0, parentShapeDimensions.Height / 2.0); double d1 = System.Math.Atan2(pointD2.Y, pointD2.X); double d2 = System.Math.Atan2(pointD1.Y - pointD2.Y, pointD1.X - pointD2.X); if ((d2 <= d1) && (d2 >= -d1)) { return(PortPlacement.Right); } if ((d2 > d1) && (d2 < (Math.PI - d1))) { return(PortPlacement.Bottom); } if ((d2 > -(Math.PI - d1)) && (d2 < -d1)) { return(PortPlacement.Top); } if ((d2 >= (Math.PI - d1)) || (d2 <= -(Math.PI - d1))) { return(PortPlacement.Left); } throw new System.InvalidOperationException(); }
/// <summary> /// Layouts the diagram. /// </summary> public virtual void Layout() { RectangleD rectSource = new RectangleD(new PointD(0, 0), new SizeD(0, 0)); RectangleD rectTarget = new RectangleD(new PointD(0, 0), new SizeD(0, 0)); double maineElementTop = 0.0; double maineElementLeft = MarginMainElementLeft; double maineElementLeftTemp = 0.0; if (this.SourceDependencyShapes.Count == 0) { maineElementLeft = MarginMainNoElementLeft; } for (int i = 0; i < this.SourceDependencyShapes.Count; i++) { GraphicalDependencyShape shape = this.SourceDependencyShapes[i]; UpdateShapeLayout(shape); rectSource.Width += shape.Size.Width; rectSource.Height += shape.Size.Height + VerticalSpaceBetweenElements; if (shape.Size.Width > maineElementLeftTemp) { maineElementLeftTemp = shape.Size.Width; } } for (int i = 0; i < this.TargetDependencyShapes.Count; i++) { GraphicalDependencyShape shape = this.TargetDependencyShapes[i]; UpdateShapeLayout(shape); rectTarget.Width += shape.Size.Width; rectTarget.Height += shape.Size.Height + VerticalSpaceBetweenElements; } if (this.SourceDependencyShapes.Count == 0 && this.TargetDependencyShapes.Count == 0) { this.MainElementShape.SetLocation( new PointD(MarginMainNoElementLeft, MarginMainNoElementTop)); } else { // position elements if (rectSource.Height > rectTarget.Height) { // first source element is positioned at 0,0 (+margins) // first target element is poisitioned at (rectSource.Height - rectTaget.Height)/2.0 // following elements are positioned at *prev element height* + margin double start = (rectSource.Height - rectTarget.Height) / 2.0 + MarginTopStart; double x = maineElementLeft + maineElementLeftTemp + this.MainElementShape.Size.Width + TargetMarginLeft; for (int i = 0; i < this.TargetDependencyShapes.Count; i++) { double y = this.TargetDependencyShapes[i].Size.Height; this.TargetDependencyShapes[i].SetLocation(new PointD(x, start)); start = start + y + VerticalSpaceBetweenElements; } start = MarginTopStart; x = SourceMarginLeft; for (int i = 0; i < this.SourceDependencyShapes.Count; i++) { double y = this.SourceDependencyShapes[i].Size.Height; this.SourceDependencyShapes[i].SetLocation(new PointD(x, start)); start = start + y + VerticalSpaceBetweenElements; } maineElementTop = rectSource.Height / 2.0 - this.MainElementShape.Size.Height / 2.0 + MarginTopStart; } else { // first target element is positioned at 0,0 (+margins) // first source element is poisitioned at (rectTaget.Height - rectSource.Height)/2.0 // following elements are positioned at *prev element height* + margin double start = (rectTarget.Height - rectSource.Height) / 2.0 + MarginTopStart; double x = SourceMarginLeft; for (int i = 0; i < this.SourceDependencyShapes.Count; i++) { double y = this.SourceDependencyShapes[i].Size.Height; this.SourceDependencyShapes[i].SetLocation(new PointD(x, start)); start = start + y + VerticalSpaceBetweenElements; } start = MarginTopStart; x = maineElementLeft + maineElementLeftTemp + this.MainElementShape.Size.Width + TargetMarginLeft; for (int i = 0; i < this.TargetDependencyShapes.Count; i++) { double y = this.TargetDependencyShapes[i].Size.Height; this.TargetDependencyShapes[i].SetLocation(new PointD(x, start)); start = start + y + VerticalSpaceBetweenElements; } maineElementTop = rectTarget.Height / 2.0 - this.MainElementShape.Size.Height / 2.0 + MarginTopStart; } this.MainElementShape.SetLocation( new PointD(maineElementLeft + maineElementLeftTemp, maineElementTop)); UpdateLinkShapePositions(); } }
/// <summary> /// Layouts the diagram. /// </summary> public virtual void Layout() { RectangleD rectSource = new RectangleD(new PointD(0, 0), new SizeD(0, 0)); RectangleD rectTarget = new RectangleD(new PointD(0, 0), new SizeD(0, 0)); double maineElementTop = 0.0; double maineElementLeft = MarginMainElementLeft; double maineElementLeftTemp = 0.0; if (this.SourceDependencyShapes.Count == 0) maineElementLeft = MarginMainNoElementLeft; for (int i = 0; i < this.SourceDependencyShapes.Count; i++) { GraphicalDependencyShape shape = this.SourceDependencyShapes[i]; UpdateShapeLayout(shape); rectSource.Width += shape.Size.Width; rectSource.Height += shape.Size.Height + VerticalSpaceBetweenElements; if (shape.Size.Width > maineElementLeftTemp) maineElementLeftTemp = shape.Size.Width; } for (int i = 0; i < this.TargetDependencyShapes.Count; i++) { GraphicalDependencyShape shape = this.TargetDependencyShapes[i]; UpdateShapeLayout(shape); rectTarget.Width += shape.Size.Width; rectTarget.Height += shape.Size.Height + VerticalSpaceBetweenElements; } if (this.SourceDependencyShapes.Count == 0 && this.TargetDependencyShapes.Count == 0) { this.MainElementShape.SetLocation( new PointD(MarginMainNoElementLeft, MarginMainNoElementTop)); } else { // position elements if (rectSource.Height > rectTarget.Height) { // first source element is positioned at 0,0 (+margins) // first target element is poisitioned at (rectSource.Height - rectTaget.Height)/2.0 // following elements are positioned at *prev element height* + margin double start = (rectSource.Height - rectTarget.Height) / 2.0 + MarginTopStart; double x = maineElementLeft + maineElementLeftTemp + this.MainElementShape.Size.Width + TargetMarginLeft; for (int i = 0; i < this.TargetDependencyShapes.Count; i++) { double y = this.TargetDependencyShapes[i].Size.Height; this.TargetDependencyShapes[i].SetLocation(new PointD(x, start)); start = start + y + VerticalSpaceBetweenElements; } start = MarginTopStart; x = SourceMarginLeft; for (int i = 0; i < this.SourceDependencyShapes.Count; i++) { double y = this.SourceDependencyShapes[i].Size.Height; this.SourceDependencyShapes[i].SetLocation(new PointD(x, start)); start = start + y + VerticalSpaceBetweenElements; } maineElementTop = rectSource.Height / 2.0 - this.MainElementShape.Size.Height / 2.0 + MarginTopStart; } else { // first target element is positioned at 0,0 (+margins) // first source element is poisitioned at (rectTaget.Height - rectSource.Height)/2.0 // following elements are positioned at *prev element height* + margin double start = (rectTarget.Height - rectSource.Height) / 2.0 + MarginTopStart; double x = SourceMarginLeft; for (int i = 0; i < this.SourceDependencyShapes.Count; i++) { double y = this.SourceDependencyShapes[i].Size.Height; this.SourceDependencyShapes[i].SetLocation(new PointD(x, start)); start = start + y + VerticalSpaceBetweenElements; } start = MarginTopStart; x = maineElementLeft + maineElementLeftTemp + this.MainElementShape.Size.Width + TargetMarginLeft; for (int i = 0; i < this.TargetDependencyShapes.Count; i++) { double y = this.TargetDependencyShapes[i].Size.Height; this.TargetDependencyShapes[i].SetLocation(new PointD(x, start)); start = start + y + VerticalSpaceBetweenElements; } maineElementTop = rectTarget.Height / 2.0 - this.MainElementShape.Size.Height / 2.0 + MarginTopStart; } this.MainElementShape.SetLocation( new PointD(maineElementLeft + maineElementLeftTemp, maineElementTop)); UpdateLinkShapePositions(); } }