// // Shape.cs // MSAGL Shape class for Rectilinear Edge Routing. // // Copyright Microsoft Corporation. using System; using System.Collections.Generic; using Microsoft.Msagl.Core.DataStructures; using Microsoft.Msagl.Core.Geometry; using Microsoft.Msagl.Core.Geometry.Curves; using Microsoft.Msagl.Core.Layout; using Microsoft.Msagl.Core; using System.Diagnostics; namespace Microsoft.Msagl.Routing { /// /// A shape wrapping an ICurve, providing additional information. /// [DebuggerDisplay("Shape = {UserData}")] public class Shape { readonly Set parents = new Set(); /// /// shape parents /// public IEnumerable Parents { get { return parents; } } readonly Set children = new Set(); /// /// shape children /// public IEnumerable Children { get { return children; } } /// /// The curve of the shape. /// public virtual ICurve BoundaryCurve { get { return boundaryCurve; } set {boundaryCurve = value; } } ICurve boundaryCurve; /// /// The bounding box of the shape. /// public Rectangle BoundingBox { get { return BoundaryCurve.BoundingBox; } } /// /// The set of Ports for this obstacle, usually RelativePorts. In the event of overlapping /// obstacles, this identifies the obstacle to which the port applies. /// public Set Ports { get { return ports; } } private readonly Set ports = new Set(); /// /// A location for storing user data associated with the Shape. /// public object UserData { get; set; } /// /// Default constructor. /// public Shape() : this (null) { } /// /// Constructor taking the ID and the curve of the shape. /// /// public Shape(ICurve boundaryCurve) { this.boundaryCurve = boundaryCurve; // RelativeShape throws an exception on BoundaryCurve_set so set _boundaryCurve directly. } /// /// A group is a shape that has children. /// public bool IsGroup { get { return children.Count > 0; } } internal bool IsTransparent { get; set; } internal IEnumerable Descendants { get { var q = new Queue(); foreach (var shape in Children) q.Enqueue(shape); while (q.Count > 0) { var sh = q.Dequeue(); yield return sh; foreach (var shape in sh.Children) q.Enqueue(shape); } } } internal IEnumerable Ancestors { get { var q = new Queue(); foreach (var shape in Parents) q.Enqueue(shape); while (q.Count > 0) { var sh = q.Dequeue(); yield return sh; foreach (var shape in sh.Parents) q.Enqueue(shape); } } } /// /// Adds a parent. A shape can have several parents /// /// public void AddParent(Shape shape) { ValidateArg.IsNotNull(shape, "shape"); parents.Insert(shape); shape.children.Insert(this); } /// /// /// public void AddChild(Shape shape) { ValidateArg.IsNotNull(shape, "shape"); shape.parents.Insert(this); children.Insert(shape); } /// /// /// /// public void RemoveChild(Shape shape) { ValidateArg.IsNotNull(shape, "shape"); children.Remove(shape); shape.parents.Remove(this); } /// /// /// /// public void RemoveParent(Shape shape) { ValidateArg.IsNotNull(shape, "shape"); parents.Remove(shape); shape.children.Remove(this); } #if TEST_MSAGL /// /// /// /// public override string ToString() { return UserData == null ? "null" : UserData.ToString(); } #endif } }