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