using System;
using System.Drawing;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.ComponentModel;
namespace Netron.Diagramming.Core
{
// ----------------------------------------------------------------------
///
/// Implementation of the interface; the 'database'
/// of the control.
///
// ----------------------------------------------------------------------
public partial class Model :
IModel,
IDisposable
{
#region Events
// ------------------------------------------------------------------
///
/// Occurs when the current page has changed.
///
// ------------------------------------------------------------------
public event CurrentPageChangedEventHandler OnCurrentPageChanged;
///
/// Occurs when an entity is removed from the model
///
public event EventHandler OnEntityRemoved;
///
/// Occurs when an entity is added to the model.
///
public event EventHandler OnEntityAdded;
///
/// Occurs when an element of the diagram requests a refresh of a region/rectangle of the canvas
///
public event EventHandler OnInvalidateRectangle;
///
/// Occurs when an element of the diagram requests a refresh
///
public event EventHandler OnInvalidate;
///
/// Occurs when the ConnectionCollection has changed
///
public event EventHandler OnConnectionCollectionChanged;
///
/// Occurs when the cursor is changed and the surface is supposed to set the cursor accordingly.
///
public event EventHandler OnCursorChange;
///
/// Raises the event
///
/// ConnectionCollection event argument
private void RaiseOnConnectionCollectionChanged(ConnectionCollectionEventArgs e)
{
EventHandler handler = OnConnectionCollectionChanged;
if (handler != null)
{
handler(this, e);
}
}
public void RaiseOnCursorChange(Cursor cursor)
{
EventHandler handler = OnCursorChange;
if(handler != null)
handler(this, new CursorEventArgs(cursor));
}
///
/// Raises the on invalidate.
///
public void RaiseOnInvalidate()
{
if (OnInvalidate != null)
OnInvalidate(this, EventArgs.Empty);
}
///
/// Raises the OnInvalidateRectangle event.
///
/// The rectangle.
public void RaiseOnInvalidateRectangle(Rectangle rectangle)
{
EventHandler handler = OnInvalidateRectangle;
if (handler != null)
{
handler(this, new RectangleEventArgs(rectangle));
}
}
///
/// Occurs when the bounding region (aka client-rectangle) of the canvas has changed
///
public event EventHandler OnRectangleChanged;
///
/// Raises the event.
///
///
private void RaiseOnRectangleChanged(RectangleEventArgs e)
{
EventHandler handler = OnRectangleChanged;
if (handler != null)
{
handler(this, e);
}
}
///
/// Occurs when the diagram info (aka user metadata) has changed
///
public event EventHandler OnDiagramInformationChanged;
///
/// Raises the event.
///
///
private void RaiseOnDiagramInformationChanged(DiagramInformationEventArgs e)
{
EventHandler handler = OnDiagramInformationChanged;
if (handler != null)
{
handler(this, e);
}
}
///
/// Occurs when the Ambience has changed
///
public event EventHandler OnAmbienceChanged;
///
/// Raises the event
///
///
private void RaiseOnAmbienceChanged(AmbienceEventArgs e)
{
EventHandler handler = OnAmbienceChanged;
if (handler != null)
{
handler(this, e);
}
}
///
/// Raises the event
///
/// The instance containing the event data.
private void RaiseOnEntityAdded(EntityEventArgs e)
{
EventHandler handler = OnEntityAdded;
if (handler != null)
{
handler(this, e);
}
}
///
/// Raises the event.
///
/// The instance containing the event data.
private void RaiseOnEntityRemoved(EntityEventArgs e)
{
EventHandler handler = OnEntityRemoved;
if (handler != null)
{
handler(this, e);
}
}
// ------------------------------------------------------------------
///
/// Raises the event.
///
/// PageEventArgs
// ------------------------------------------------------------------
protected virtual void RaiseOnCurrentPageChanged(PageEventArgs e)
{
if (this.OnCurrentPageChanged != null)
{
OnCurrentPageChanged(this, e);
}
}
#endregion
#region Fields
// ------------------------------------------------------------------
///
/// Implementation of IVersion - the current version of
/// Model.
///
// ------------------------------------------------------------------
protected const double modelVersion = 1.0;
// ------------------------------------------------------------------
///
/// Specifies if all shape's connectors are shown.
///
// ------------------------------------------------------------------
protected bool mShowConnectors = true;
private GraphicsUnit measurementUnits = GraphicsUnit.Pixel;
///
/// the LayoutRoot field
///
private IShape mLayoutRoot;
///
/// the DefaultPage field
///
[NonSerialized]
private IPage mDefaultPage;
///
/// the page collection
///
[NonSerialized]
private CollectionBase mPages;
///
/// the shapes of the diagram
///
[NonSerialized]
private CollectionBase mShapes;
///
/// the bounding rectangle
///
[NonSerialized]
private Rectangle mRectangle;
///
/// the metadata of the diagram
///
[NonSerialized]
private DocumentInformation mInformation;
///
/// the collection of to-be-painted diagram entities
///
//[NonSerialized]
//private CollectionBase Paintables;
///
/// the CurrentPage field
///
[NonSerialized]
private IPage mCurrentPage;
private float mMeasurementScale = 1.0F;
#endregion
#region Properties
// ------------------------------------------------------------------
///
/// Gets the current version.
///
// ------------------------------------------------------------------
public virtual double Version
{
get
{
return modelVersion;
}
}
// ------------------------------------------------------------------
///
/// Specifies if all shape's connectors are shown.
///
// ------------------------------------------------------------------
public bool ShowConnectors
{
get
{
return this.mShowConnectors;
}
set
{
this.mShowConnectors = value;
foreach (IPage page in this.mPages)
{
foreach (IShape shape in page.Shapes)
{
shape.ShowConnectors = this.mShowConnectors;
}
}
}
}
[Browsable(true)]
[Description("Scaling value for logical units.")]
public float MeasurementScale
{
get
{
return mMeasurementScale;
}
set
{
mMeasurementScale = value;
}
}
[BrowsableAttribute(true)]
[Description("Logical unit of measurement")]
public GraphicsUnit MeasurementUnits
{
get
{
return measurementUnits;
}
set
{
measurementUnits = value;
}
}
// ------------------------------------------------------------------
///
/// Gets or sets the LayoutRoot
///
// ------------------------------------------------------------------
public IShape LayoutRoot
{
get { return mLayoutRoot; }
set { mLayoutRoot = value;
}
}
// ------------------------------------------------------------------
///
/// Gets the current page. Use 'SetCurrentPage(IPage page)' or
/// 'SetCurrentPage(int index)' to set the current page.
///
// ------------------------------------------------------------------
public IPage CurrentPage
{
get { return mCurrentPage; }
}
// ------------------------------------------------------------------
///
/// Gets the paintables.
///
/// The paintables.
// ------------------------------------------------------------------
public CollectionBase Paintables
{
get
{
return mCurrentPage.Entities;
}
}
// ------------------------------------------------------------------
///
/// Gets the pages of the diagram control. Use method 'AddPage' to
/// add a page so the page gets attached to this Model.
///
/// The pages.
// ------------------------------------------------------------------
public CollectionBase Pages
{
get { return mPages; }
}
// ------------------------------------------------------------------
///
/// Gets or sets the default page
///
// ------------------------------------------------------------------
public IPage DefaultPage
{
get { return mDefaultPage; }
set { mDefaultPage = value; }
}
// ------------------------------------------------------------------
///
/// Gets the shapes of the current page.
///
// ------------------------------------------------------------------
public CollectionBase Shapes
{
get
{
return CurrentPage.Shapes;
//return mShapes;
}
//internal set
//{
// mShapes = value;
//}
}
// ------------------------------------------------------------------
///
/// Gets or sets the information of the diagram
///
// ------------------------------------------------------------------
internal DocumentInformation Information
{
get
{
return mInformation;
}
set
{
mInformation = value;
}
}
// ------------------------------------------------------------------
///
/// Gets the bounding rectangle of the diagram (client rectangle)
///
// ------------------------------------------------------------------
public Rectangle Rectangle
{
get
{
return mRectangle;
}
set
{
mRectangle = value;
RaiseOnRectangleChanged(new RectangleEventArgs(value));
}
}
// ------------------------------------------------------------------
///
/// Gets the horizontal coordinate of the diagram
///
// ------------------------------------------------------------------
public float X
{
get
{
return mRectangle.X;
}
}
// ------------------------------------------------------------------
///
/// Gets the verticle coordinate of the diagram
///
// ------------------------------------------------------------------
public float Y
{
get
{
return mRectangle.Y;
}
}
// ------------------------------------------------------------------
///
/// Gets the width of the diagram
///
// ------------------------------------------------------------------
public float Width
{
get
{
return mRectangle.Width;
}
}
// ------------------------------------------------------------------
///
/// Gets the height of the diagram
///
// ------------------------------------------------------------------
public float Height
{
get
{
return mRectangle.Height;
}
}
// ------------------------------------------------------------------
///
/// Gets or sets the collection of connections
///
// ------------------------------------------------------------------
public CollectionBase Connections
{
get
{
throw new System.NotImplementedException();
}
}
#endregion
#region Constructor
// ------------------------------------------------------------------
///
/// Default constructor
///
// ------------------------------------------------------------------
public Model()
{
//here I'll have to work on the scene graph
//this.mShapes = new CollectionBase();
//the default page
//the page collection
mPages = new CollectionBase();
Page p = new Page("Default Page", this);
p.Ambience.PageColor = ArtPalette.DefaultPageColor;
mPages.Add(p);
Init();
}
#endregion
// ------------------------------------------------------------------
///
/// Initializes this object
/// See also the event for
/// post-deserialization actions to which this method is related.
///
///
// ------------------------------------------------------------------
private void Init()
{
if (mPages == null)
{
throw new InconsistencyException(
"The page collection is 'null'.");
}
if (mPages.Count == 0)
{
throw new InconsistencyException(
"The page collection should contain at least one page.");
}
foreach(IPage page in mPages)
AttachToPage(page);
mDefaultPage = mPages[0];
// Initially the current page is the zero-th page in the
// collection.
SetCurrentPage(0);
}
// ------------------------------------------------------------------
///
/// Adds a page. This should be used when adding pages rather than
/// though the Pages property so the page gets attached to the Model.
///
/// IPage: The page to add.
/// IPage
// ------------------------------------------------------------------
public IPage AddPage(IPage page)
{
mPages.Add(page);
AttachToPage(page);
return page;
}
// ------------------------------------------------------------------
///
/// Adds a page. This should be used when adding pages rather than
/// though the Pages property so the page gets attached to the Model.
/// The page name is set to "Page" plus the new number of pages.
/// For example, if there are currently two pages, then "Page3" is
/// set as the new page name.
///
/// IPage
// ------------------------------------------------------------------
public IPage AddPage()
{
string pageName = this.GetDefaultNewPageName();
Page page = new Page(pageName, this);
return AddPage(page);
}
// ------------------------------------------------------------------
///
/// Deletes the page specified if it is not the default page.
///
/// IPage: The page to remove.
/// bool: Specifies if the user should
/// be given the option to cancel the action if the current page
/// has entities. Also, when set to true, if the current page is
/// the default page, then a message box is shown informing the
/// user that the default page cannot be deleted.
/// bool: If the delete was successful. True is returned
/// if the current page was removed.
// ------------------------------------------------------------------
public bool RemovePage(IPage page, bool allowWarnings)
{
if (page == this.DefaultPage)
{
if (allowWarnings)
{
MessageBox.Show(
"The default page cannot be deleted.",
"Delete Page Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
return false;
}
int pageIndex = 0;
int newCurrentPageIndex = 0;
// Ask the user if they really want to remove the page if
// it has entities if 'allowWarnings' is true.
if ((allowWarnings) && (page.Entities.Count > 0))
{
if (MessageBox.Show(
"Are you sure you want to delete this page?",
"Confirm Delete",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button1) == DialogResult.No)
{
return false;
}
}
// Now we can continue with deleting the page.
// If the page specified is the current page, then we need to set
// the current page to another page. Let's use the previous one
// in the list.
if (page == CurrentPage)
{
pageIndex = Pages.IndexOf(page);
if (pageIndex > 0)
{
newCurrentPageIndex = pageIndex - 1;
}
SetCurrentPage(newCurrentPageIndex);
}
Pages.Remove(page);
return true;
}
// ------------------------------------------------------------------
///
/// Returns a new page name that's unique from all the others.
///
/// string: Returns "Page" plus the number of pages IF A
/// NEW PAGE WERE ADDED. For example, if there are currently two
/// pages, then "Page3" is returned.
// ------------------------------------------------------------------
public string GetDefaultNewPageName()
{
string name = "Page" + (Pages.Count + 1).ToString();
return name;
}
// ------------------------------------------------------------------
///
/// Sets the current page.
///
/// The page.
// ------------------------------------------------------------------
public void SetCurrentPage(IPage page)
{
mCurrentPage = page;
RaiseOnAmbienceChanged(new AmbienceEventArgs(page.Ambience));
RaiseOnCurrentPageChanged(new PageEventArgs(page));
//change the paintables as well
//Paintables = new CollectionBase();
#region Reload of the z-order, usually only necessary after deserialization
CollectionBase collected = new CollectionBase();
//pick up the non-group entities
foreach (IDiagramEntity entity in Paintables)
if (!typeof(IGroup).IsInstanceOfType(entity))
collected.Add(entity);
if (collected.Count > 0)
{
Algorithms.SortInPlace(collected, new SceneIndexComparer());
//Paintables.AddRange(collected);
}
#endregion
}
// ------------------------------------------------------------------
///
/// Sets the current page.
///
/// Index of the page.
// ------------------------------------------------------------------
public void SetCurrentPage(int pageIndex)
{
if (mPages == null ||
mPages.Count == 0 ||
pageIndex >= mPages.Count ||
pageIndex < 0)
{
throw new IndexOutOfRangeException(
"The page index is outside the page range.");
}
SetCurrentPage(mPages[pageIndex]);
}
// ------------------------------------------------------------------
///
/// Attaches this model to the page specified. The Model property for
/// the page is set and the IPage events needed by this are registered
/// for here (OnEntityAdded, OnEntityRemoved, OnClear, and
/// OnAmbienceChanged).
///
/// IPage: The page to attach this model to.
// ------------------------------------------------------------------
private void AttachToPage(IPage page)
{
page.OnEntityAdded += new EventHandler(mDefaultPage_OnEntityAdded);
page.OnEntityRemoved += new EventHandler(mDefaultPage_OnEntityRemoved);
page.OnClear += new EventHandler(mDefaultPage_OnClear);
page.OnAmbienceChanged += new EventHandler(mDefaultPage_OnAmbienceChanged);
page.Model = this;
}
void mDefaultPage_OnAmbienceChanged(object sender, AmbienceEventArgs e)
{
RaiseOnAmbienceChanged(e);
}
#region Paintables transfers on Page changes
// ------------------------------------------------------------------
///
/// Handles the OnClear event of the DefaultPage.
///
/// The source of the event.
/// The instance
/// containing the event data.
// ------------------------------------------------------------------
void mDefaultPage_OnClear(object sender, EventArgs e)
{
Paintables.Clear();
}
// ------------------------------------------------------------------
///
/// Handles the OnEntityRemoved event of the DefaultPage.
///
/// The source of the event.
/// The
/// instance
/// containing the event data.
// ------------------------------------------------------------------
void mDefaultPage_OnEntityRemoved(object sender, EntityEventArgs e)
{
if(Paintables.Contains(e.Entity))
{
//shift the entities above the one to be removed
int index = e.Entity.SceneIndex;
foreach(IDiagramEntity entity in Paintables)
{
if(entity.SceneIndex > index)
entity.SceneIndex--;
}
Paintables.Remove(e.Entity);
}
//if the selection contains the shape we have to remove it from the selection
if (Selection.SelectedItems.Contains(e.Entity))
{
Selection.SelectedItems.Remove(e.Entity);
}
RaiseOnEntityRemoved(e);
}
// ------------------------------------------------------------------
///
/// Handles the OnEntityAdded event of the Page and adds the new
/// entity to the Paintables.
///
/// The source of the event.
/// The
/// instance
/// containing the event data.
// ------------------------------------------------------------------
void mDefaultPage_OnEntityAdded(object sender, EntityEventArgs e)
{
//don't add it if it's already there or if it's a group (unless you want to deploy something special to emphasize a group shape).
if (!Paintables.Contains(e.Entity) )
{
if ((e.Entity is IGroup) && !(e.Entity as IGroup).EmphasizeGroup)
{
return;
}
//set the new entity on top of the stack
e.Entity.SceneIndex = Paintables.Count;
Paintables.Add(e.Entity);
}
#region Addition callback
IAdditionCallback callback = e.Entity.GetService(typeof(IAdditionCallback)) as IAdditionCallback;
if (callback != null)
callback.OnAddition();
#endregion
RaiseOnEntityAdded(e);
}
#endregion
#region Methods
#region Ordering methods
///
/// Re-sets the scene-index of the paintables
///
private void ReAssignSceneIndex(CollectionBase entities)
{
for (int i = 0; i < entities.Count; i++)
{
entities[i].SceneIndex = i;
}
}
///
/// Sends to entity to the bottom of the z-order stack.
///
/// The entity.
public void SendToBack(IDiagramEntity entity)
{
ILayer layer = CurrentPage.GetLayer(entity);
if (layer != null)
{
layer.Entities.Remove(entity);
layer.Entities.Insert(0, entity);
ReAssignSceneIndex(layer.Entities);
Rectangle rec = entity.Rectangle;
rec.Inflate(20, 20);
this.RaiseOnInvalidateRectangle(Rectangle);
}
//if(Paintables.Contains(entity))
//{
// Paintables.Remove(entity);
// Paintables.Insert(0, entity);
// ReAssignSceneIndex();
// Rectangle rec = entity.Rectangle;
// rec.Inflate(20, 20);
// this.RaiseOnInvalidateRectangle(Rectangle);
//}
}
///
/// Sends the entity down the z-order stack with the specified amount.
///
/// The entity.
/// The z shift.
public void SendBackwards(IDiagramEntity entity, int zShift)
{
ILayer layer = CurrentPage.GetLayer(entity);
if (layer != null)
{
int newpos = layer.Entities.IndexOf(entity) - zShift;
//if this is the first in the row you cannot move it lower
if (newpos >= 0)
{
layer.Entities.Remove(entity);
layer.Entities.Insert(newpos, entity);
ReAssignSceneIndex(layer.Entities);
Rectangle rec = entity.Rectangle;
rec.Inflate(20, 20);
this.RaiseOnInvalidateRectangle(Rectangle);
}
}
//if (Paintables.Contains(entity))
//{
// int newpos = Paintables.IndexOf(entity) - zShift;
// //if this is the first in the row you cannot move it lower
// if (newpos >= 0)
// {
// Paintables.Remove(entity);
// Paintables.Insert(newpos, entity);
// ReAssignSceneIndex(Paintables);
// Rectangle rec = entity.Rectangle;
// rec.Inflate(20, 20);
// this.RaiseOnInvalidateRectangle(Rectangle);
// }
//}
}
///
/// Sends the entity one level down the z-order stack.
///
/// The entity.
public void SendBackwards(IDiagramEntity entity)
{
SendBackwards(entity, 1);
}
///
/// Sends the entity to the top of the z-order stack.
///
/// The entity.
public void SendForwards(IDiagramEntity entity)
{
SendForwards(entity, 1);
}
///
/// Sends the entity up the z-order stack with the specified amount.
///
/// The entity.
/// The z shift.
public void SendForwards(IDiagramEntity entity, int zShift)
{
ILayer layer = CurrentPage.GetLayer(entity);
if (layer != null)
{
int newpos = layer.Entities.IndexOf(entity) + zShift;
//if this is the last in the row you cannot move it higher
if (newpos < layer.Entities.Count)
{
layer.Entities.Remove(entity);
layer.Entities.Insert(newpos, entity); //does it works when this is an addition at the top?
ReAssignSceneIndex(layer.Entities);
Rectangle rec = entity.Rectangle;
rec.Inflate(20, 20);
this.RaiseOnInvalidateRectangle(Rectangle);
}
}
//if (Paintables.Contains(entity) && zShift>=1)
//{
// int newpos = Paintables.IndexOf(entity) + zShift;
// //if this is the last in the row you cannot move it higher
// if (newpos < Paintables.Count)
// {
// Paintables.Remove(entity);
// Paintables.Insert(newpos, entity); //does it works when this is an addition at the top?
// ReAssignSceneIndex(Paintables);
// Rectangle rec = entity.Rectangle;
// rec.Inflate(20, 20);
// this.RaiseOnInvalidateRectangle(Rectangle);
// }
//}
}
///
/// Sends the entity to the front of the z-order stack.
///
/// The entity.
public void SendToFront(IDiagramEntity entity)
{
ILayer layer = CurrentPage.GetLayer(entity);
if (layer != null)
{
layer.Entities.Remove(entity);
layer.Entities.Add(entity);
ReAssignSceneIndex(layer.Entities);
Rectangle rec = entity.Rectangle;
rec.Inflate(20, 20);
this.RaiseOnInvalidateRectangle(Rectangle);
}
//if(Paintables.Contains(entity))
//{
// Paintables.Remove(entity);
// Paintables.Add(entity);
// ReAssignSceneIndex(Paintables);
// Rectangle rec = entity.Rectangle;
// rec.Inflate(20, 20);
// this.RaiseOnInvalidateRectangle(Rectangle);
//}
}
#endregion
#region Diagram manipulation actions
// ------------------------------------------------------------------
///
/// Returns the number of shapes in the current page that are of
/// the type specified.
///
/// Type
/// int
// ------------------------------------------------------------------
public int NumberOfShapes(Type type)
{
int count = 0;
foreach (IShape shape in Shapes)
{
if (shape.GetType() == type)
{
count++;
}
}
return count;
}
// ------------------------------------------------------------------
///
/// Gets the shape at the specified location. If no shape could be
/// found then 'null' is returned.
///
/// Point: The location in world
/// coordinates.
/// IShape
// ------------------------------------------------------------------
public IShape GetShapeAt(Point surfacePoint)
{
foreach (IShape shape in this.CurrentPage.Shapes)
{
if (shape.Hit(surfacePoint))
{
return shape;
}
}
return null;
}
// ------------------------------------------------------------------
///
/// Adds an entity to the diagram. The magnification level for the
/// entity is set to the current magnification level of the current
/// page.
///
/// IDiagramEntity: The entity to add.
/// IDiagramEntity: The added entity.
// ------------------------------------------------------------------
public IDiagramEntity AddEntity(IDiagramEntity entity)
{
SetModel(entity);
//By default the new entity is added to the default layer in the
// current page.
CurrentPage.DefaultLayer.Entities.Add(entity);
entity.Attached(CurrentPage.DefaultLayer);
entity.Magnification = CurrentPage.Magnification;
return entity;
}
// ------------------------------------------------------------------
///
/// Adds a shape to the diagram
///
/// IShape: The shape to add.
/// IShape: The added shape.
// ------------------------------------------------------------------
public IShape AddShape(IShape shape)
{
SetModel(shape);
// By default the new shape is added to the default layer in the
// current page.
CurrentPage.DefaultLayer.Entities.Add(shape);
shape.Attached(CurrentPage.DefaultLayer);
shape.ShowConnectors = this.mShowConnectors;
return shape;
}
// ------------------------------------------------------------------
///
/// Adds a connection to the diagram
///
/// a connection
// ------------------------------------------------------------------
public IConnection AddConnection(IConnection connection)
{
SetModel(connection);
CurrentPage.DefaultLayer.Entities.Add(connection);
connection.Attached(CurrentPage.DefaultLayer);
return connection;
}
// ------------------------------------------------------------------
///
/// Adds a connection between two shape connectors.
///
/// From connector.
/// To connector.
// ------------------------------------------------------------------
public IConnection AddConnection(IConnector from, IConnector to)
{
Connection con = new Connection(from.Point, to.Point);
this.AddConnection(con);
return con;
}
// ------------------------------------------------------------------
///
/// Sets the model (recursively) on the given entity.
///
/// The entity.
// ------------------------------------------------------------------
public void SetModel(IDiagramEntity entity)
{
if(entity is IConnector)
{
(entity as IConnector).Model = this;
}
else if(entity is IConnection)
{
IConnection con = entity as IConnection;
con.Model = this;
Debug.Assert(con.From != null, "The 'From' connector is not set.");
con.From.Model = this;
Debug.Assert(con.From != null, "The 'To' connector is not set.");
con.To.Model = this;
}
else if(entity is IShape)
{
IShape shape = entity as IShape;
shape.Model = this;
foreach(IConnector co in shape.Connectors)
{
co.Model = this;
}
}
else if (entity is IGroup)
{
IGroup group = entity as IGroup;
group.Model = this;
foreach (IDiagramEntity child in group.Entities)
{
SetModel(child);
}
}
}
// ------------------------------------------------------------------
///
/// Removes the shape from the diagram.
///
/// The shape.
// ------------------------------------------------------------------
public void RemoveShape(IShape shape)
{
//remove it from the layer(s)
foreach (IPage page in mPages)
{
foreach (ILayer layer in page.Layers)
{
if (layer.Entities.Contains(shape))
{
layer.Entities.Remove(shape);
shape.Detached(CurrentPage.DefaultLayer);
}
}
}
// The old way, when there weren't multiple pages and layers.
//if (CurrentPage.DefaultLayer.Entities.Contains(shape))
//{
// CurrentPage.DefaultLayer.Entities.Remove(shape);
// shape.Detached(CurrentPage.DefaultLayer);
//}
}
// ------------------------------------------------------------------
///
/// Removes all entities that are currently selected.
///
/// The entity.
// ------------------------------------------------------------------
public void RemoveSelectedItems()
{
if (Selection.SelectedItems.Count < 1)
{
return;
}
int numberOfItems = Selection.SelectedItems.Count;
for (int i = 0; i < numberOfItems - 1; i++)
{
IDiagramEntity entity = Selection.SelectedItems[0];
foreach (IPage page in mPages)
{
foreach (ILayer layer in page.Layers)
{
if (layer.Entities.Contains(entity))
{
layer.Entities.Remove(entity);
entity.Detached(DefaultPage.DefaultLayer);
}
}
}
}
}
// ------------------------------------------------------------------
///
/// Removes the specified entity.
///
/// The entity.
// ------------------------------------------------------------------
public void Remove(IDiagramEntity entity)
{
if (CurrentPage.DefaultLayer.Entities.Contains(entity))
{
CurrentPage.DefaultLayer.Entities.Remove(entity);
entity.Detached(CurrentPage.DefaultLayer);
}
}
// ------------------------------------------------------------------
///
/// Adds a collection of entities to the diagram
///
/// The collection.
// ------------------------------------------------------------------
public void AddEntities(CollectionBase collection)
{
foreach (IDiagramEntity entity in collection)
{
SetModel(entity);
CurrentPage.DefaultLayer.Entities.Add(entity);
entity.Attached(CurrentPage.DefaultLayer);
}
}
// ------------------------------------------------------------------
///
/// Unwraps an entity
///
/// UidGenerates a new for the entity.
/// ModelAssigns the Model property to the entity.
///
///
///
// ------------------------------------------------------------------
public void Unwrap(IDiagramEntity entity)
{
//set a new unique identifier for this copied object
entity.NewUid(true);
//this assignment will be recursive if needed
SetModel(entity);
CurrentPage.DefaultLayer.Entities.Add(entity);
entity.Attached(CurrentPage.DefaultLayer);
}
// ------------------------------------------------------------------
///
/// Unwraps the specified collection.
///
/// The collection.
// ------------------------------------------------------------------
public void Unwrap(CollectionBase collection)
{
if (collection == null)
return;
foreach (IDiagramEntity entity in collection)
{
Unwrap(entity);
}
//reconnect the connectors, just like the deserialization of a filed diagram
Dictionary.Enumerator enumer = Anchors.GetEnumerator();
System.Collections.Generic.KeyValuePair pair;
Anchor anchor;
while (enumer.MoveNext())
{
pair = enumer.Current;
anchor = pair.Value;
if (anchor.Parent != Guid.Empty) //there's a parent connector
{
if (Anchors.ContainsKey(anchor.Parent))
{
Anchors.GetAnchor(anchor.Parent).Instance.AttachConnector(anchor.Instance);
}
}
}
//clean up the anchoring matrix
Anchors.Clear();
}
// ------------------------------------------------------------------
///
/// Clears the current page.
///
// ------------------------------------------------------------------
public void Clear()
{
//clear the scene-graph
this.CurrentPage.DefaultLayer.Entities.Clear();
}
#endregion
#endregion
#region Standard IDispose implementation
// ------------------------------------------------------------------
///
/// Disposes the view.
///
// ------------------------------------------------------------------
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// ------------------------------------------------------------------
///
/// Disposes the view.
///
/// if set to true [disposing].
// ------------------------------------------------------------------
private void Dispose(bool disposing)
{
if (disposing)
{
}
}
#endregion
}
}