Пример #1
0
        /// <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();
        }
Пример #2
0
        /// <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));
        }
Пример #3
0
        /// <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));
        }
Пример #4
0
        /// <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);
                }
            }
        }
Пример #5
0
 static RectangleD()
 {
     RectangleD.Empty = new RectangleD(0.0, 0.0, 0.0, 0.0);
 }
Пример #6
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;
 }
Пример #7
0
        /// <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);
            }
        }
Пример #9
0
        /// <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);
        }
Пример #10
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);
        }
Пример #11
0
 /// <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);
 }
Пример #12
0
        /// <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();
        }
Пример #13
0
 static RectangleD()
 {
     RectangleD.Empty = new RectangleD(0.0, 0.0, 0.0, 0.0);
 }
Пример #14
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));
        }
Пример #15
0
        /// <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();
        }
Пример #16
0
        /// <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();
            }
        }