Exemple #1
0
		/// <summary>
		/// Resolves references between shapes (indicated as lines on the diagram)
		/// </summary>
		/// <param name="list">Any list of <seealso cref="LayoutShape"/>s that need to have the shape references resolved</param>
		/// <returns>The shape with the most references in the list (typically treated as the root shape)</returns>
		/// <remarks>Any <see cref="LayoutShape"/> where the <see cref="LayoutShape.Placed"/> property is <see langword="true"/>
		/// should be ignored.</remarks>
		public override LayoutShape ResolveReferences(LayoutShapeList list)
		{
			LayoutShape mostChildren = null;
			LayoutShapeList allShapes = myLayoutShapes;
			foreach (LayoutShape layshape in list)
			{
				if (!layshape.Placed)
				{
					layshape.ResolveReferences(allShapes);
					if ((mostChildren == null || layshape.Count > mostChildren.Count) && !(layshape.Shape is FactTypeShape) && !(layshape.Shape is ExternalConstraintShape))
					{
						mostChildren = layshape;
					}
				}
			}
			return mostChildren;
		}
        /// <summary>
        /// Resolves references between shapes (indicated as lines on the diagram)
        /// </summary>
        /// <param name="list">Any list of <seealso cref="LayoutShape"/>s that need to have the shape references resolved</param>
        /// <returns>The shape with the most references in the list (typically treated as the root shape)</returns>
        /// <remarks>Any <see cref="LayoutShape"/> where the <see cref="LayoutShape.Placed"/> property is <see langword="true"/>
        /// should be ignored.</remarks>
        public override LayoutShape ResolveReferences(LayoutShapeList list)
        {
            LayoutShape     mostChildren = null;
            LayoutShapeList allShapes    = myLayoutShapes;

            foreach (LayoutShape layshape in list)
            {
                if (!layshape.Placed)
                {
                    layshape.ResolveReferences(allShapes);
                    if ((mostChildren == null || layshape.Count > mostChildren.Count) && !(layshape.Shape is FactTypeShape) && !(layshape.Shape is ExternalConstraintShape))
                    {
                        mostChildren = layshape;
                    }
                }
            }
            return(mostChildren);
        }
Exemple #3
0
        /// <summary>
        /// Adds the <paramref name="shape"/> with the specified <paramref name="pinned"/> value.
        /// </summary>
        /// <param name="shape">The shape to lay out on the diagram.</param>
        /// <param name="pinned">Indicates whether the shape is pinned in place or not.  True means the shape is pinned to its current location.</param>
        public void AddShape(ShapeElement shape, bool pinned)
        {
            NodeShape ns = shape as NodeShape;

            if (ns == null || shape.ParentShape as ORMDiagram == null)
            {
                return;
            }

            LayoutShapeList list = myLayoutShapes;
            LayoutShape     layshape;

            // If the shape doesn't exist, add it, otherwise simply modify the pinned value.
            if (!list.TryGetValue(ns, out layshape))
            {
                layshape = new LayoutShape(ns, pinned);
                list.Add(layshape);
            }
            else
            {
                layshape.Pinned = pinned;
            }
        }
Exemple #4
0
        /// <summary>
        /// Organizes the shapes added with <see cref="AddShape(ShapeElement)"/> or similar methods.
        /// </summary>
        /// <param name="ignoreExistingShapes">Do not adjust for existing shapes</param>
        /// <param name="referenceShape">Layout shapes to the right of this shape.</param>
        /// <param name="layoutRightOfReferenceShape">Set to layout to the right of the <paramref name="referenceShape"/></param>
        /// <param name="layoutBelowReferenceShape">Set to layout below the <paramref name="referenceShape"/></param>
        public void Layout(bool ignoreExistingShapes, NodeShape referenceShape, bool layoutRightOfReferenceShape, bool layoutBelowReferenceShape)
        {
            LayoutShape     backupRoot = null;
            LayoutShapeList allShapes  = myLayoutShapes;

            switch (allShapes.Count)
            {
            case 0:
                return;

            default:
                backupRoot = allShapes[0];
                break;
            }
            myLayoutEngine.LateBind(myDiagram, allShapes);

            SizeD margin = myDiagram.NestedShapesMargin;

            if (referenceShape != null &&
                (layoutRightOfReferenceShape || layoutBelowReferenceShape))
            {
                RectangleD referenceBounds = referenceShape.AbsoluteBounds;
                if (layoutRightOfReferenceShape)
                {
                    margin.Width = Math.Max(margin.Width, referenceBounds.Right);
                }
                if (layoutBelowReferenceShape)
                {
                    margin.Height = Math.Max(margin.Height, referenceBounds.Bottom);
                }
            }
            PointD     minimumPoint    = new PointD(margin.Width, margin.Height);
            RectangleD layoutRectangle = new RectangleD(minimumPoint, SizeD.Empty);
            bool       firstPass       = true;

            for (; ;)
            {
                LayoutShape mostRelatives = myLayoutEngine.ResolveReferences(allShapes);
                LayoutShape root          = null;
                // If the root shape was set by the user, AND the shape exists in our shape list
                if (myRootShape == null || !allShapes.TryGetValue(myRootShape, out root))
                {
                    root = GetRoot(mostRelatives);
                }
                if (root == null)
                {
                    if (backupRoot == null)
                    {
                        myLayoutEngine.PostLayout(minimumPoint);
                        break;
                    }
                    root = backupRoot;
                }

                // run the layout of base shapes
                myLayoutEngine.PerformLayout(root, new PointD(margin.Width, layoutRectangle.Bottom + (firstPass ? 0 : root.Shape.Size.Height)), ref layoutRectangle);
                firstPass   = false;
                backupRoot  = null;
                myRootShape = null;
            }

            Reflow(ignoreExistingShapes);
        }
        /// <summary>
        /// Places each external constraint shape at the point corresponding to the average of all of its referenced shapes.
        /// Frequency constraints are handled differently, since they apply to only one fact type (but 1 or more roles in that
        /// fact type) at any time.
        /// </summary>
        /// <param name="minimumPoint">The minimum location for new element placement</param>
        public override void PostLayout(PointD minimumPoint)
        {
            ResolveReferences(myConstraintShapes);

            foreach (LayoutShape shape in myConstraintShapes)
            {
                if (!shape.Pinned)
                {
                    PointD    avg       = new PointD(0, 0);
                    NodeShape nodeShape = shape.Shape;
                    FrequencyConstraintShape           freqShape;
                    FrequencyConstraint                constraint;
                    LinkedElementCollection <FactType> relatedFactTypes;
                    int count;

                    if (null != (freqShape = nodeShape as FrequencyConstraintShape) &&
                        null != (constraint = freqShape.ModelElement as FrequencyConstraint) &&
                        1 == (relatedFactTypes = constraint.FactTypeCollection).Count)
                    {
                        Diagram       diagram             = myDiagram;
                        FactType      factType            = relatedFactTypes[0];
                        FactTypeShape factTypeShape       = null;
                        LayoutShape   factTypeLayoutShape = null;
                        foreach (PresentationElement pel in PresentationViewsSubject.GetPresentation(factType))
                        {
                            FactTypeShape testShape = pel as FactTypeShape;
                            if (testShape != null && testShape.Diagram == diagram)
                            {
                                if (factTypeShape == null)
                                {
                                    factTypeShape = testShape;
                                }
                                if (myLayoutShapes.TryGetValue(testShape, out factTypeLayoutShape))
                                {
                                    factTypeShape = testShape;
                                    break;
                                }
                            }
                        }

                        LinkedElementCollection <Role>     constraintRoles = constraint.RoleCollection;
                        LinkedElementCollection <RoleBase> displayOrder    = factTypeShape.DisplayedRoleOrder;
                        DisplayOrientation orientation = factTypeShape.DisplayOrientation;
                        RectangleD         shapeBounds = factTypeShape.AbsoluteBounds;
                        SizeD  shapeSize = factTypeShape.Size;
                        PointD location  = (factTypeLayoutShape != null) ? factTypeLayoutShape.TargetLocation : shapeBounds.Location;
                        count = constraintRoles.Count;
                        double width  = shapeSize.Width;
                        double height = shapeSize.Height;

                        for (int i = 0; i < count; i++)
                        {
                            int targetIndex = displayOrder.IndexOf(constraintRoles[i]);
                            switch (orientation)
                            {
                            case DisplayOrientation.Horizontal:
                                avg.Offset((width / (targetIndex + 1)) + location.X, location.Y - height);
                                break;

                            case DisplayOrientation.VerticalRotatedRight:
                                avg.Offset(location.X + width, (height / (targetIndex + 1)) + location.Y);
                                break;

                            case DisplayOrientation.VerticalRotatedLeft:
                                avg.Offset(location.X + width, height - (height / (targetIndex + 1)) + location.Y);
                                break;
                            }
                        }
                        avg.X /= count;
                        avg.Y /= count;
                    }
                    else if (0 != (count = shape.Count))
                    {
                        double          minX = double.MaxValue;
                        double          minY = double.MaxValue;
                        double          maxX = 0;
                        double          maxY = 0;
                        SizeD           size;
                        LayoutShapeList relatedShapes = shape.RelatedShapes;
                        // Take the center of farthest bounds as the location.
                        // This is the same as the average for two elements, but
                        // balances more than two elements much better.
                        for (int i = 0; i < count; ++i)
                        {
                            LayoutShape relatedShape = relatedShapes[i];
                            PointD      location     = relatedShape.TargetLocation;
                            size = relatedShape.Shape.Size;
                            double x = location.X + size.Width / 2;
                            double y = location.Y + size.Height / 2;
                            minX = Math.Min(minX, x);
                            minY = Math.Min(minY, y);
                            maxX = Math.Max(maxX, x);
                            maxY = Math.Max(maxY, y);
                        }
                        size  = nodeShape.Size;
                        avg.X = (maxX + minX) / 2 - size.Width / 2;
                        avg.Y = (maxY + minY) / 2 - size.Height / 2;
                        // Constraints are frequently ending up directly on top of
                        // an ObjectTypeShape, bump them up a bit
                        double bumpAdjust = size.Height * 2;
                        avg.Y -= bumpAdjust;
                        if (avg.Y < minimumPoint.Y)
                        {
                            avg.Y += bumpAdjust + bumpAdjust;
                        }
                    }

                    shape.TargetLocation = avg;
                }
                shape.Placed = true;
            }

            // Now add the shapes back into the main myLayoutShape list for reflow
            foreach (LayoutShape shape in myConstraintShapes)
            {
                myLayoutShapes.Add(shape);
            }
            myConstraintShapes.Clear();
        }