using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; namespace Netron.Diagramming.Core { // ---------------------------------------------------------------------- /// /// Abstract base class for complex shapes . /// // ---------------------------------------------------------------------- public abstract partial class ComplexShapeBase : ShapeBase, IComplexShape, IMouseListener, IHoverListener { #region Fields // ------------------------------------------------------------------ /// /// Implementation of IVersion - the current version of /// ComplexShapeBase. /// // ------------------------------------------------------------------ protected const double complexShapeVersion = 1.0; /// /// the text on the bundle /// protected string mText = string.Empty; /// /// the shape children or sub-controls /// protected CollectionBase mChildren; #endregion #region Properties // ------------------------------------------------------------------ /// /// Gets the current version. /// // ------------------------------------------------------------------ public override double Version { get { return complexShapeVersion; } } // ------------------------------------------------------------------ /// /// Gets or sets the text of the bundle /// // ------------------------------------------------------------------ [Browsable(true), Description("The text shown on the shape"), Category("Layout")] public virtual string Text { get { return mText; } set { mText = value; this.Invalidate(); } } #endregion #region Constructor // ------------------------------------------------------------------ /// ///Default constructor /// // ------------------------------------------------------------------ public ComplexShapeBase() : base() { } // ------------------------------------------------------------------ /// /// Initializes a new instance of the /// class. /// /// // ------------------------------------------------------------------ public ComplexShapeBase(IModel model) : base(model) { } // ------------------------------------------------------------------ /// /// Initializes this instance. /// // ------------------------------------------------------------------ protected override void Initialize() { base.Initialize(); mChildren = new CollectionBase(); mChildren.OnItemAdded += new EventHandler> (mChildren_OnItemAdded); } #endregion #region Methods // ------------------------------------------------------------------ /// /// Sets some contextual properties of the /// when a new item is added. /// /// The sender. /// The e. // ------------------------------------------------------------------ void mChildren_OnItemAdded(object sender, CollectionEventArgs e) { e.Item.Shape = this; } // ------------------------------------------------------------------ /// /// Overrides the abstract paint method /// /// a graphics object onto which to paint // ------------------------------------------------------------------ public override void Paint(Graphics g) { base.Paint(g); foreach (IPaintable material in Children) { material.Paint(g); } } // ------------------------------------------------------------------ /// /// Moves the entity with the given shift /// /// represent a shift-vector, not the absolute /// position! // ------------------------------------------------------------------ public override void MoveBy(Point p) { base.MoveBy(p); Rectangle rec; foreach (IShapeMaterial material in Children) { rec = material.Rectangle; rec.Offset(p.X, p.Y); material.Transform(rec); } } // ------------------------------------------------------------------ /// /// Transforms the entity to the given new rectangle. /// /// The x-coordinate of the new rectangle. /// The y-coordinate of the new rectangle. /// The width. /// The height. // ------------------------------------------------------------------ public override void Transform(int x, int y, int width, int height) { if (Children != null && Children.Count > 0) { int a, b, w, h; foreach (IShapeMaterial material in Children) { if (material.Gliding) { a = Convert.ToInt32(Math.Round(((double)material.Rectangle.X - (double)Rectangle.X) / (double)Rectangle.Width * width, 1) + x); b = Convert.ToInt32(Math.Round(((double)material.Rectangle.Y - (double)Rectangle.Y) / (double)Rectangle.Height * height, 1) + y); } else //shift the material, do not scale the position with respect to the sizing of the shape { a = material.Rectangle.X - Rectangle.X + x; b = material.Rectangle.Y - Rectangle.Y + y; } if (material.Resizable) { w = Convert.ToInt32(Math.Round(((double)material.Rectangle.Width) / ((double)Rectangle.Width), 1) * width); h = Convert.ToInt32(Math.Round(((double)material.Rectangle.Height) / ((double)Rectangle.Height), 1) * height); } else { w = material.Rectangle.Width; h = material.Rectangle.Height; } material.Transform(new Rectangle(a, b, w, h)); } } base.Transform(x, y, width, height); } #endregion // ------------------------------------------------------------------ /// /// Gets or sets the children. /// /// The children. // ------------------------------------------------------------------ public virtual CollectionBase Children { get { return mChildren; } set { throw new InconsistencyException("You cannot set the children, use the existing collection and the clear() method."); } } // ------------------------------------------------------------------ /// /// Defines a mechanism for retrieving a service object; that is, an /// object that provides custom support to other objects. /// /// An object that specifies the type of /// service object to get. /// /// A service object of type serviceType.-or- null if there is no /// service object of type serviceType. /// // ------------------------------------------------------------------ public override object GetService(Type serviceType) { if (Services.ContainsKey(serviceType)) return Services[serviceType]; else { return null; } } // ------------------------------------------------------------------ /// /// implementation. /// /// The /// instance /// containing the event data. // ------------------------------------------------------------------ public override bool MouseDown(MouseEventArgs e) { base.MouseDown(e); IMouseListener listener; foreach (IShapeMaterial material in mChildren) { if (material.Rectangle.Contains(e.Location) && material.Visible) { listener = material.GetService(typeof( IMouseListener)) as IMouseListener; if (listener != null) if (listener.MouseDown(e)) return true; } } return false; } // ------------------------------------------------------------------ /// /// implementation. /// /// The /// instance /// containing the event data. // ------------------------------------------------------------------ public override void MouseMove(MouseEventArgs e) { base.MouseMove(e); IMouseListener listener; foreach (IShapeMaterial material in mChildren) { if ((material.Rectangle.Contains(e.Location)) && (material.Visible)) { listener = material.GetService(typeof (IMouseListener)) as IMouseListener; if (listener != null) { listener.MouseMove(e); } } } } // ------------------------------------------------------------------ /// /// implementation. /// /// The /// instance /// containing the event data. // ------------------------------------------------------------------ public override void MouseUp(MouseEventArgs e) { base.MouseUp(e); IMouseListener listener; foreach (IShapeMaterial material in mChildren) { if (material.Rectangle.Contains(e.Location) && material.Visible) { listener = material.GetService(typeof(IMouseListener)) as IMouseListener; if (listener != null) listener.MouseUp(e); } } } #region IHoverListener Members private IHoverListener currentHoveredMaterial; // ------------------------------------------------------------------ /// /// Handles the MouseHover event. /// /// The /// instance /// containing the event data. // ------------------------------------------------------------------ public override void MouseHover(MouseEventArgs e) { base.MouseHover(e); IHoverListener listener; foreach (IShapeMaterial material in this.Children) { if (material.Rectangle.Contains(e.Location) && material.Visible) //we caught an material and it's visible { listener = material.GetService(typeof(IHoverListener)) as IHoverListener; if (listener != null) //the caught material does listen { if (currentHoveredMaterial == listener) //it's the same as the previous time listener.MouseHover(e); else //we moved from one material to another listening material { if (currentHoveredMaterial != null) //tell the previous material we are leaving currentHoveredMaterial.MouseLeave(e); listener.MouseEnter(e); //tell the current one we enter currentHoveredMaterial = listener; } } else //the caught material does not listen { if (currentHoveredMaterial != null) { currentHoveredMaterial.MouseLeave(e); currentHoveredMaterial = null; } } return; //only one material at a time } } if (currentHoveredMaterial != null) { currentHoveredMaterial.MouseLeave(e); currentHoveredMaterial = null; } } // ------------------------------------------------------------------ /// /// Handles the OnMouseEnter event. /// /// The /// instance /// containing the event data. // ------------------------------------------------------------------ public override void MouseEnter(MouseEventArgs e) { base.MouseEnter(e); } // ------------------------------------------------------------------ /// /// Handles the OnMouseLeave event. /// /// The /// instance /// containing the event data. // ------------------------------------------------------------------ public override void MouseLeave(MouseEventArgs e) { base.MouseLeave(e); } #endregion } }