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