//
// 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
}
}