using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Netron.Diagramming.Core {
public class Shape : ShapeBase {
// ------------------------------------------------------------------
///
/// The collection of shapes.
///
// ------------------------------------------------------------------
CollectionBase myEntities;
// ------------------------------------------------------------------
///
/// Gets the friendly name of this shape.
///
// ------------------------------------------------------------------
public override string EntityName {
get {
return "Shape";
}
}
// ------------------------------------------------------------------
///
/// Gets or set the owned shapes.
///
// ------------------------------------------------------------------
public CollectionBase Entities {
get {
return myEntities;
}
set {
myEntities = value;
}
}
public virtual GraphicsPath GraphicsPath {
get {
GraphicsPath path = new GraphicsPath();
path.AddRectangle(mRectangle);
return path;
}
}
// ------------------------------------------------------------------
///
/// Default constructor.
///
// ------------------------------------------------------------------
public Shape()
: base() {
}
// ------------------------------------------------------------------
///
/// Constructor that receives the model this shape belongs to.
///
/// IModel
// ------------------------------------------------------------------
public Shape(IModel model)
: base(model) {
}
protected override void Initialize() {
base.Initialize();
myEntities = new CollectionBase();
AttachEventsToShapeCollection();
}
protected virtual void AttachEventsToShapeCollection() {
myEntities.OnClear += new EventHandler(OnEntitiesClear);
myEntities.OnItemAdded +=
new EventHandler>(
OnEntityAdded);
myEntities.OnItemRemoved +=
new EventHandler>(
OnEntityRemoved);
}
void OnEntityRemoved(object sender, CollectionEventArgs e) {
CalculateRectangle();
}
void OnEntityAdded(object sender, CollectionEventArgs e) {
if (myEntities.Count == 1) {
mRectangle = e.Item.Rectangle;
} else {
mRectangle = Rectangle.Union(
(Rectangle)mRectangle,
e.Item.Rectangle);
}
}
void OnEntitiesClear(object sender, EventArgs e) {
mRectangle = Rectangle.Empty;
}
// ------------------------------------------------------------------
///
/// Calculates the bounding rectangle of this shape from all children.
///
// ------------------------------------------------------------------
public void CalculateRectangle() {
if (myEntities == null || myEntities.Count == 0)
return;
Rectangle rec = myEntities[0].Rectangle;
foreach (IDiagramEntity entity in Entities) {
//cascade the calculation if necessary
if (entity is IGroup) (entity as IGroup).CalculateRectangle();
rec = Rectangle.Union(rec, entity.Rectangle);
}
this.mRectangle = rec;
this.mRectangle.Inflate(20, 20);
}
// ------------------------------------------------------------------
///
/// Tests whether the group is hit by the mouse
///
/// Point
/// bool
// ------------------------------------------------------------------
public override bool Hit(Point p) {
foreach (IDiagramEntity entity in myEntities) {
if (entity.Hit(p)) {
return true;
}
}
return false;
}
// ------------------------------------------------------------------
///
/// Invalidates the entity
///
// ------------------------------------------------------------------
public override void Invalidate() {
if (mRectangle == null)
return;
Rectangle rec = mRectangle;
rec.Inflate(20, 20);
Model.RaiseOnInvalidateRectangle(rec);
}
// ------------------------------------------------------------------
///
/// Moves the entity on the canvas
///
/// Point
// ------------------------------------------------------------------
public override void MoveBy(Point p) {
Rectangle recBefore = mRectangle;
recBefore.Inflate(20, 20);
// No need to invalidate since it'll be done by the individual
// move actions.
foreach (IDiagramEntity entity in myEntities) {
entity.MoveBy(p);
}
mRectangle.X += p.X;
mRectangle.Y += p.Y;
//refresh things
this.Invalidate(recBefore);//position before the move
this.Invalidate();//current position
}
public override void Paint(Graphics g) {
base.Paint(g);
GraphicsPath path = GraphicsPath;
if (PaintStyle != null) {
g.FillPath(mPaintStyle.GetBrush(mRectangle), path);
}
if (Hovered) {
g.DrawPath(ArtPalette.HighlightPen, path);
} else if (PenStyle != null) {
g.DrawPath(mPenStyle.DrawingPen(), path);
}
foreach (IDiagramEntity entity in myEntities) {
entity.Paint(g);
}
}
public override bool MouseDown(System.Windows.Forms.MouseEventArgs e) {
bool result = base.MouseDown(e);
foreach (IDiagramEntity entity in myEntities) {
if (entity.Hit(e.Location)) {
this.Model.Selection.SelectedItems.Add(entity);
if (entity.MouseDown(e)) {
result = true;
}
}
}
return result;
}
}
}