Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.Netron/3.0.2672.12446/Netron.Diagramming.Core-3.0.2672.12446/Core/Scene graph/Model.cs @ 3038

Last change on this file since 3038 was 3038, checked in by mkommend, 14 years ago

removed warnings from HeuristicLab.Netron (ticket #915)

File size: 49.0 KB
Line 
1using System;
2using System.Drawing;
3using System.Collections.Generic;
4using System.Text;
5using System.Diagnostics;
6using System.Windows.Forms;
7using System.ComponentModel;
8namespace Netron.Diagramming.Core
9{
10    // ----------------------------------------------------------------------
11    /// <summary>
12    /// Implementation of the <see cref="IModel"/> interface; the 'database'
13    /// of the control.
14    /// </summary>
15    // ----------------------------------------------------------------------
16    public partial class Model :
17        IModel,
18        IDisposable
19    {
20        #region Events
21
22        // ------------------------------------------------------------------
23        /// <summary>
24        /// Occurs when the current page has changed.
25        /// </summary>
26        // ------------------------------------------------------------------
27        public event CurrentPageChangedEventHandler OnCurrentPageChanged;
28
29        /// <summary>
30        /// Occurs when an entity is removed from the model
31        /// </summary>
32        public event EventHandler<EntityEventArgs> OnEntityRemoved;
33        /// <summary>
34        /// Occurs when an entity is added to the model.
35        /// </summary>
36        public event EventHandler<EntityEventArgs> OnEntityAdded;
37        /// <summary>
38        /// Occurs when an element of the diagram requests a refresh of a region/rectangle of the canvas
39        /// </summary>
40        public event EventHandler<RectangleEventArgs> OnInvalidateRectangle;
41        /// <summary>
42        /// Occurs when an element of the diagram requests a refresh
43        /// </summary>
44        public event EventHandler OnInvalidate;
45        /// <summary>
46        /// Occurs when the ConnectionCollection has changed
47        /// </summary>
48        public event EventHandler<ConnectionCollectionEventArgs> OnConnectionCollectionChanged;
49        /// <summary>
50        /// Occurs when the cursor is changed and the surface is supposed to set the cursor accordingly.
51        /// </summary>
52        public event EventHandler<CursorEventArgs> OnCursorChange;
53        /// <summary>
54        /// Raises the <see cref="OnConnectionCollectionChanged"/> event
55        /// </summary>
56        /// <param name="e">ConnectionCollection event argument</param>
57        private void RaiseOnConnectionCollectionChanged(ConnectionCollectionEventArgs e)
58        {
59            EventHandler<ConnectionCollectionEventArgs> handler = OnConnectionCollectionChanged;
60            if (handler != null)
61            {
62                handler(this, e);
63            }
64        }
65
66        public void RaiseOnCursorChange(Cursor cursor)
67        {
68            EventHandler<CursorEventArgs> handler = OnCursorChange;
69            if(handler != null)
70                handler(this, new CursorEventArgs(cursor));
71        }
72
73        /// <summary>
74        /// Raises the on invalidate.
75        /// </summary>
76        public void RaiseOnInvalidate()
77        {
78            if (OnInvalidate != null)
79                OnInvalidate(this, EventArgs.Empty);
80        }
81        /// <summary>
82        /// Raises the OnInvalidateRectangle event.
83        /// </summary>
84        /// <param name="rectangle">The rectangle.</param>
85        public void RaiseOnInvalidateRectangle(Rectangle rectangle)
86        {
87            EventHandler<RectangleEventArgs> handler = OnInvalidateRectangle;
88            if (handler != null)
89            {
90                handler(this, new RectangleEventArgs(rectangle));
91            }
92        }
93        /// <summary>
94        /// Occurs when the bounding region (aka client-rectangle) of the canvas has changed
95        /// </summary>
96        public event EventHandler<RectangleEventArgs> OnRectangleChanged;
97        /// <summary>
98        /// Raises the <see cref="OnRectangleChanged"/> event.
99        /// </summary>
100        /// <param name="e"></param>
101        private void RaiseOnRectangleChanged(RectangleEventArgs e)
102        {
103            EventHandler<RectangleEventArgs> handler = OnRectangleChanged;
104            if (handler != null)
105            {
106                handler(this, e);
107            }
108        }
109        /// <summary>
110        /// Occurs when the diagram info (aka user metadata) has changed
111        /// </summary>
112        public event EventHandler<DiagramInformationEventArgs> OnDiagramInformationChanged;
113        /// <summary>
114        /// Raises the <see cref="OnDiagramInformationChanged"/> event.
115        /// </summary>
116        /// <param name="e"></param>
117        private void RaiseOnDiagramInformationChanged(DiagramInformationEventArgs e)
118        {
119            EventHandler<DiagramInformationEventArgs> handler = OnDiagramInformationChanged;
120            if (handler != null)
121            {
122                handler(this, e);
123            }
124        }
125       
126        /// <summary>
127        /// Occurs when the Ambience has changed
128        /// </summary>
129        public event EventHandler<AmbienceEventArgs> OnAmbienceChanged;
130        /// <summary>
131        /// Raises the <see cref="OnAmbienceChanged"/> event
132        /// </summary>
133        /// <param name="e"></param>
134        private void RaiseOnAmbienceChanged(AmbienceEventArgs e)
135        {
136            EventHandler<AmbienceEventArgs> handler = OnAmbienceChanged;
137            if (handler != null)
138            {
139                handler(this, e);
140            }
141        }
142
143        /// <summary>
144        /// Raises the <see cref="OnEntityAdded"/> event
145        /// </summary>
146        /// <param name="e">The <see cref="T:Netron.Diagramming.Core.EntityEventArgs"/> instance containing the event data.</param>
147        private void RaiseOnEntityAdded(EntityEventArgs e)
148        {
149            EventHandler<EntityEventArgs> handler = OnEntityAdded;
150            if (handler != null)
151            {
152                handler(this, e);
153            }
154        }
155
156        /// <summary>
157        /// Raises the <see cref="OnEntityRemoved"/> event.
158        /// </summary>
159        /// <param name="e">The <see cref="T:Netron.Diagramming.Core.EntityEventArgs"/> instance containing the event data.</param>
160        private void RaiseOnEntityRemoved(EntityEventArgs e)
161        {
162            EventHandler<EntityEventArgs> handler = OnEntityRemoved;
163            if (handler != null)
164            {
165                handler(this, e);
166            }
167        }
168
169        // ------------------------------------------------------------------
170        /// <summary>
171        /// Raises the <see cref="OnCurrentPageChanged"/> event.
172        /// </summary>
173        /// <param name="e">PageEventArgs</param>
174        // ------------------------------------------------------------------
175        protected virtual void RaiseOnCurrentPageChanged(PageEventArgs e)
176        {
177            if (this.OnCurrentPageChanged != null)
178            {
179                OnCurrentPageChanged(this, e);
180            }
181        }
182
183        #endregion
184
185        #region Fields
186
187        // ------------------------------------------------------------------
188        /// <summary>
189        /// Implementation of IVersion - the current version of
190        /// Model.
191        /// </summary>
192        // ------------------------------------------------------------------
193        protected const double modelVersion = 1.0;
194
195        // ------------------------------------------------------------------
196        /// <summary>
197        /// Specifies if all shape's connectors are shown.
198        /// </summary>
199        // ------------------------------------------------------------------
200        protected bool mShowConnectors = true;
201
202        private GraphicsUnit measurementUnits = GraphicsUnit.Pixel;
203        /// <summary>
204        /// the LayoutRoot field
205        /// </summary>
206        private IShape mLayoutRoot;
207        /// <summary>
208        /// the DefaultPage field
209        /// </summary>
210        [NonSerialized]
211        private IPage mDefaultPage;
212        /// <summary>
213        /// the page collection
214        /// </summary>
215        [NonSerialized]
216        private CollectionBase<IPage> mPages;
217        ///<summary>
218        /// the shapes of the diagram
219        /// </summary>
220        //[NonSerialized]
221        //private CollectionBase<IShape> mShapes;
222        /// <summary>
223        /// the bounding rectangle
224        /// </summary>
225        [NonSerialized]       
226        private Rectangle mRectangle;
227        /// <summary>
228        /// the metadata of the diagram
229        /// </summary>
230        [NonSerialized]
231        private DocumentInformation mInformation;
232     
233        /// <summary>
234        /// the collection of to-be-painted diagram entities
235        /// </summary>
236        //[NonSerialized]
237        //private CollectionBase<IDiagramEntity> Paintables;
238        /// <summary>
239        /// the CurrentPage field
240        /// </summary>
241        [NonSerialized]
242        private IPage mCurrentPage;
243
244        private float mMeasurementScale = 1.0F;
245        #endregion
246
247        #region Properties
248
249        // ------------------------------------------------------------------
250        /// <summary>
251        /// Gets the current version.
252        /// </summary>
253        // ------------------------------------------------------------------
254        public virtual double Version
255        {
256            get
257            {
258                return modelVersion;
259            }
260        }
261
262        private Selection selection;
263        public Selection Selection {
264          get { return this.selection; }
265          set { this.selection = value; }
266        }
267
268        // ------------------------------------------------------------------
269        /// <summary>
270        /// Specifies if all shape's connectors are shown.
271        /// </summary>
272        // ------------------------------------------------------------------
273        public bool ShowConnectors
274        {
275            get
276            {
277                return this.mShowConnectors;
278            }
279            set
280            {
281                this.mShowConnectors = value;
282                foreach (IPage page in this.mPages)
283                {
284                    foreach (IShape shape in page.Shapes)
285                    {
286                        shape.ShowConnectors = this.mShowConnectors;
287                    }
288                }
289            }
290        }
291
292        [Browsable(true)]
293        [Description("Scaling value for logical units.")]
294        public float MeasurementScale
295        {
296            get
297            {
298                return mMeasurementScale;
299            }
300
301            set
302            {
303                mMeasurementScale = value;
304            }
305        }
306
307        [BrowsableAttribute(true)]
308        [Description("Logical unit of measurement")]
309        public  GraphicsUnit MeasurementUnits
310        {
311            get
312            {
313                return measurementUnits;
314            }
315
316            set
317            {
318                measurementUnits = value;
319            }
320        }
321
322        // ------------------------------------------------------------------
323        /// <summary>
324        /// Gets or sets the LayoutRoot
325        /// </summary>
326        // ------------------------------------------------------------------
327        public IShape LayoutRoot
328        {
329            get { return mLayoutRoot; }
330            set { mLayoutRoot = value;
331               
332            }
333        }
334
335        // ------------------------------------------------------------------       
336        /// <summary>
337        /// Gets the current page.  Use 'SetCurrentPage(IPage page)' or
338        /// 'SetCurrentPage(int index)' to set the current page.
339        /// </summary>
340        // ------------------------------------------------------------------
341        public IPage CurrentPage
342        {
343            get { return mCurrentPage; }
344        }
345
346        // ------------------------------------------------------------------
347        /// <summary>
348        /// Gets the paintables.
349        /// </summary>
350        /// <value>The paintables.</value>
351        // ------------------------------------------------------------------
352        public CollectionBase<IDiagramEntity> Paintables
353        {
354            get
355            {
356                return mCurrentPage.Entities;
357            }
358        }
359
360        // ------------------------------------------------------------------
361        /// <summary>
362        /// Gets the pages of the diagram control.  Use method 'AddPage' to
363        /// add a page so the page gets attached to this Model.
364        /// </summary>
365        /// <value>The pages.</value>
366        // ------------------------------------------------------------------
367        public CollectionBase<IPage> Pages
368        {
369            get { return mPages; }
370        }
371
372        // ------------------------------------------------------------------
373        /// <summary>
374        /// Gets or sets the default page
375        /// </summary>
376        // ------------------------------------------------------------------
377        public  IPage DefaultPage
378        {
379            get { return mDefaultPage; }
380            set { mDefaultPage = value; }
381        }
382
383        // ------------------------------------------------------------------
384        /// <summary>
385        /// Gets the shapes of the current page.
386        /// </summary>
387        // ------------------------------------------------------------------
388        public CollectionBase<IShape> Shapes
389        {
390            get
391            {
392                return CurrentPage.Shapes;
393                //return mShapes;
394            }
395            //internal set
396            //{
397            //    mShapes = value;
398            //}
399        }
400
401        // ------------------------------------------------------------------
402        /// <summary>
403        /// Gets or sets the information of the diagram
404        /// </summary>
405        // ------------------------------------------------------------------
406        internal DocumentInformation Information
407        {
408            get
409            {
410                return mInformation;
411            }
412            set
413            {
414                mInformation = value;
415            }
416        }
417
418        // ------------------------------------------------------------------
419        /// <summary>
420        /// Gets the bounding rectangle of the diagram (client rectangle)
421        /// </summary>
422        // ------------------------------------------------------------------
423        public Rectangle Rectangle
424        {
425            get
426            {
427                return mRectangle;
428            }
429            set
430            {
431                mRectangle = value;
432                RaiseOnRectangleChanged(new RectangleEventArgs(value));
433            }
434        }
435
436        // ------------------------------------------------------------------
437        /// <summary>
438        /// Gets the horizontal coordinate of the diagram
439        /// </summary>
440        // ------------------------------------------------------------------
441        public float X
442        {
443            get
444            {
445                return mRectangle.X;
446            }           
447        }
448
449        // ------------------------------------------------------------------
450        /// <summary>
451        /// Gets the verticle coordinate of the diagram
452        /// </summary>
453        // ------------------------------------------------------------------
454        public float Y
455        {
456            get
457            {
458                return mRectangle.Y;
459            }
460           
461        }
462
463        // ------------------------------------------------------------------
464        /// <summary>
465        /// Gets the width of the diagram
466        /// </summary>
467        // ------------------------------------------------------------------
468        public float Width
469        {
470            get
471            {
472                return mRectangle.Width;
473            }
474        }
475
476        // ------------------------------------------------------------------
477        /// <summary>
478        /// Gets the height of the diagram
479        /// </summary>
480        // ------------------------------------------------------------------
481        public float Height
482        {
483            get
484            {
485                return mRectangle.Height;
486            }           
487        }
488
489        // ------------------------------------------------------------------
490        /// <summary>
491        /// Gets or sets the collection of connections
492        /// </summary>
493        // ------------------------------------------------------------------
494        public CollectionBase<IConnection> Connections
495        {
496            get
497            {
498              return CurrentPage.Connections;
499            }
500
501        }
502        #endregion
503
504        #region Constructor
505
506        // ------------------------------------------------------------------
507        /// <summary>
508        /// Default constructor
509        /// </summary>
510        // ------------------------------------------------------------------
511        public Model()
512        {
513            //here I'll have to work on the scene graph
514            //this.mShapes = new CollectionBase<IShape>();
515            //the default page
516           
517            //the page collection
518            mPages = new CollectionBase<IPage>();
519            Page p = new Page("Default Page", this);
520            p.Ambience.PageColor = ArtPalette.DefaultPageColor;
521            mPages.Add(p);
522
523            Init();
524        }
525
526        #endregion
527
528        // ------------------------------------------------------------------
529        /// <summary>
530        /// Initializes this object
531        /// <remarks>See also the <see cref="OnDeserialized"/> event for
532        /// post-deserialization actions to which this method is related.
533        /// </remarks>
534        /// </summary>
535        // ------------------------------------------------------------------
536        private void Init()
537        {
538            if (mPages == null)
539            {
540                throw new InconsistencyException(
541                    "The page collection is 'null'.");
542            }
543            if (mPages.Count == 0)
544            {
545                throw new InconsistencyException(
546                    "The page collection should contain at least one page.");
547            }
548
549            foreach(IPage page in mPages)
550                AttachToPage(page);
551            mDefaultPage = mPages[0];           
552            // Initially the current page is the zero-th page in the
553            // collection.
554            SetCurrentPage(0);
555        }
556
557        // ------------------------------------------------------------------
558        /// <summary>
559        /// Adds a page.  This should be used when adding pages rather than
560        /// though the Pages property so the page gets attached to the Model.
561        /// </summary>
562        /// <param name="page">IPage: The page to add.</param>
563        /// <returns>IPage</returns>
564        // ------------------------------------------------------------------
565        public IPage AddPage(IPage page)
566        {
567            mPages.Add(page);
568            AttachToPage(page);
569            return page;
570        }
571
572        // ------------------------------------------------------------------
573        /// <summary>
574        /// Adds a page.  This should be used when adding pages rather than
575        /// though the Pages property so the page gets attached to the Model.
576        /// The page name is set to "Page" plus the new number of pages.
577        /// For example, if there are currently two pages, then "Page3" is
578        /// set as the new page name.
579        /// </summary>
580        /// <returns>IPage</returns>
581        // ------------------------------------------------------------------
582        public IPage AddPage()
583        {
584            string pageName = this.GetDefaultNewPageName();
585            Page page = new Page(pageName, this);
586            return AddPage(page);
587        }
588
589        // ------------------------------------------------------------------
590        /// <summary>
591        /// Deletes the page specified if it is not the default page.
592        /// </summary>
593        /// <param name="page">IPage: The page to remove.</param>
594        /// <param name="allowWarnings">bool: Specifies if the user should
595        /// be given the option to cancel the action if the current page
596        /// has entities.  Also, when set to true, if the current page is
597        /// the default page, then a message box is shown informing the
598        /// user that the default page cannot be deleted.</param>
599        /// <returns>bool: If the delete was successful.  True is returned
600        /// if the current page was removed.</returns>
601        // ------------------------------------------------------------------
602        public bool RemovePage(IPage page, bool allowWarnings)
603        {
604            if (page == this.DefaultPage)
605            {
606                if (allowWarnings)
607                {
608                    MessageBox.Show(
609                    "The default page cannot be deleted.",
610                    "Delete Page Error",
611                    MessageBoxButtons.OK,
612                    MessageBoxIcon.Error);
613                }
614                return false;
615            }
616
617            int pageIndex = 0;
618            int newCurrentPageIndex = 0;
619
620            // Ask the user if they really want to remove the page if
621            // it has entities if 'allowWarnings' is true.
622            if ((allowWarnings) && (page.Entities.Count > 0))
623            {
624                if (MessageBox.Show(
625                    "Are you sure you want to delete this page?",
626                    "Confirm Delete",
627                    MessageBoxButtons.YesNo,
628                    MessageBoxIcon.Question,
629                    MessageBoxDefaultButton.Button1) == DialogResult.No)
630                {
631                    return false;
632                }
633            }
634
635            // Now we can continue with deleting the page.
636            // If the page specified is the current page, then we need to set
637            // the current page to another page.  Let's use the previous one
638            // in the list. 
639            if (page == CurrentPage)
640            {
641                pageIndex = Pages.IndexOf(page);
642
643                if (pageIndex > 0)
644                {
645                    newCurrentPageIndex = pageIndex - 1;
646                }
647                SetCurrentPage(newCurrentPageIndex);
648            }
649
650            Pages.Remove(page);
651            return true;
652        }
653
654        // ------------------------------------------------------------------
655        /// <summary>
656        /// Returns a new page name that's unique from all the others.
657        /// </summary>
658        /// <returns>string: Returns "Page" plus the number of pages IF A
659        /// NEW PAGE WERE ADDED.  For example, if there are currently two
660        /// pages, then "Page3" is returned.</returns>
661        // ------------------------------------------------------------------
662        public string GetDefaultNewPageName()
663        {
664            string name = "Page" + (Pages.Count + 1).ToString();
665            return name;
666        }
667
668        // ------------------------------------------------------------------
669        /// <summary>
670        /// Sets the current page.
671        /// </summary>
672        /// <param name="page">The page.</param>
673        // ------------------------------------------------------------------
674        public void SetCurrentPage(IPage page)
675        {
676            mCurrentPage = page;
677            RaiseOnAmbienceChanged(new AmbienceEventArgs(page.Ambience));
678            RaiseOnCurrentPageChanged(new PageEventArgs(page));
679
680            //change the paintables as well           
681            //Paintables = new CollectionBase<IDiagramEntity>();
682
683            #region Reload of the z-order, usually only necessary after deserialization
684
685            CollectionBase<IDiagramEntity> collected = new CollectionBase<IDiagramEntity>();
686            //pick up the non-group entities
687            foreach (IDiagramEntity entity in Paintables)
688                if (!typeof(IGroup).IsInstanceOfType(entity))
689                    collected.Add(entity);
690
691            if (collected.Count > 0)
692            {
693                Algorithms.SortInPlace<IDiagramEntity>(collected, new SceneIndexComparer<IDiagramEntity>());
694                //Paintables.AddRange(collected);
695            }
696            #endregion           
697               
698        }
699
700        // ------------------------------------------------------------------
701        /// <summary>
702        /// Sets the current page.
703        /// </summary>
704        /// <param name="pageIndex">Index of the page.</param>
705        // ------------------------------------------------------------------
706        public void SetCurrentPage(int pageIndex)
707        {
708            if (mPages == null ||
709                mPages.Count == 0 ||
710                pageIndex >= mPages.Count ||
711                pageIndex < 0)
712            {
713                throw new IndexOutOfRangeException(
714                    "The page index is outside the page range.");
715            }
716            SetCurrentPage(mPages[pageIndex]);
717        }
718
719        // ------------------------------------------------------------------
720        /// <summary>
721        /// Attaches this model to the page specified.  The Model property for
722        /// the page is set and the IPage events needed by this are registered
723        /// for here (OnEntityAdded, OnEntityRemoved, OnClear, and
724        /// OnAmbienceChanged).
725        /// </summary>
726        /// <param name="page">IPage: The page to attach this model to.</param>
727        // ------------------------------------------------------------------
728        private void AttachToPage(IPage page)
729        {
730            page.OnEntityAdded += new EventHandler<EntityEventArgs>(mDefaultPage_OnEntityAdded);
731            page.OnEntityRemoved += new EventHandler<EntityEventArgs>(mDefaultPage_OnEntityRemoved);
732            page.OnClear += new EventHandler(mDefaultPage_OnClear);
733            page.OnAmbienceChanged += new EventHandler<AmbienceEventArgs>(mDefaultPage_OnAmbienceChanged);
734            page.Model = this;
735        }
736
737        void mDefaultPage_OnAmbienceChanged(object sender, AmbienceEventArgs e)
738        {
739            RaiseOnAmbienceChanged(e);
740        }
741
742        #region Paintables transfers on Page changes
743
744        // ------------------------------------------------------------------
745        /// <summary>
746        /// Handles the OnClear event of the DefaultPage.
747        /// </summary>
748        /// <param name="sender">The source of the event.</param>
749        /// <param name="e">The <see cref="T:System.EventArgs"/> instance
750        /// containing the event data.</param>
751        // ------------------------------------------------------------------
752        void mDefaultPage_OnClear(object sender, EventArgs e)
753        {
754            Paintables.Clear();
755        }
756
757        // ------------------------------------------------------------------
758        /// <summary>
759        /// Handles the OnEntityRemoved event of the DefaultPage.
760        /// </summary>
761        /// <param name="sender">The source of the event.</param>
762        /// <param name="e">The
763        /// <see cref="T:Netron.Diagramming.Core.EntityEventArgs"/> instance
764        /// containing the event data.</param>
765        // ------------------------------------------------------------------
766        void mDefaultPage_OnEntityRemoved(object sender, EntityEventArgs e)
767        {
768            if(Paintables.Contains(e.Entity))
769            {
770                //shift the entities above the one to be removed
771                int index = e.Entity.SceneIndex;
772                foreach(IDiagramEntity entity in Paintables)
773                {
774                    if(entity.SceneIndex > index)
775                        entity.SceneIndex--;
776                }
777                Paintables.Remove(e.Entity);
778            }
779            //if the selection contains the shape we have to remove it from the selection
780            if (Selection.SelectedItems.Contains(e.Entity))
781            {
782                Selection.SelectedItems.Remove(e.Entity);               
783            }
784            RaiseOnEntityRemoved(e);
785        }
786
787        // ------------------------------------------------------------------
788        /// <summary>
789        /// Handles the OnEntityAdded event of the Page and adds the new
790        /// entity to the Paintables.
791        /// </summary>
792        /// <param name="sender">The source of the event.</param>
793        /// <param name="e">The
794        /// <see cref="T:Netron.Diagramming.Core.EntityEventArgs"/> instance
795        /// containing the event data.</param>
796        // ------------------------------------------------------------------
797        void mDefaultPage_OnEntityAdded(object sender, EntityEventArgs e)
798        {
799            //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).
800            if (!Paintables.Contains(e.Entity) )
801            {
802                if ((e.Entity is IGroup) && !(e.Entity as IGroup).EmphasizeGroup)
803                {
804                    return;
805                }
806                //set the new entity on top of the stack
807                e.Entity.SceneIndex = Paintables.Count;
808                Paintables.Add(e.Entity);
809            }
810            #region Addition callback
811            IAdditionCallback callback = e.Entity.GetService(typeof(IAdditionCallback)) as IAdditionCallback;
812            if (callback != null)
813                callback.OnAddition();
814            #endregion
815            RaiseOnEntityAdded(e);
816        }
817        #endregion
818
819        #region Methods
820
821        #region Ordering methods
822        /// <summary>
823        /// Re-sets the scene-index of the paintables
824        /// </summary>
825        private void ReAssignSceneIndex(CollectionBase<IDiagramEntity> entities)
826        {
827            for (int i = 0; i < entities.Count; i++)
828            {
829                entities[i].SceneIndex = i;
830            }
831        }
832        /// <summary>
833        /// Sends to entity to the bottom of the z-order stack.
834        /// </summary>
835        /// <param name="entity">The entity.</param>
836        public void SendToBack(IDiagramEntity entity)
837        {
838            ILayer layer = CurrentPage.GetLayer(entity);
839            if (layer != null)
840            {
841                layer.Entities.Remove(entity);
842                layer.Entities.Insert(0, entity);
843                ReAssignSceneIndex(layer.Entities);
844                Rectangle rec = entity.Rectangle;
845                rec.Inflate(20, 20);
846                this.RaiseOnInvalidateRectangle(Rectangle);
847            }
848            //if(Paintables.Contains(entity))
849            //{
850            //    Paintables.Remove(entity);
851            //    Paintables.Insert(0, entity);
852            //    ReAssignSceneIndex();
853            //    Rectangle rec = entity.Rectangle;
854            //    rec.Inflate(20, 20);
855            //    this.RaiseOnInvalidateRectangle(Rectangle);
856            //}
857        }
858
859        /// <summary>
860        /// Sends the entity down the z-order stack with the specified amount.
861        /// </summary>
862        /// <param name="entity">The entity.</param>
863        /// <param name="zShift">The z shift.</param>
864        public void SendBackwards(IDiagramEntity entity, int zShift)
865        {
866            ILayer layer = CurrentPage.GetLayer(entity);
867            if (layer != null)
868            {
869                int newpos = layer.Entities.IndexOf(entity) - zShift;
870                //if this is the first in the row you cannot move it lower
871                if (newpos >= 0)
872                {
873                    layer.Entities.Remove(entity);
874                    layer.Entities.Insert(newpos, entity);
875                    ReAssignSceneIndex(layer.Entities);
876                    Rectangle rec = entity.Rectangle;
877                    rec.Inflate(20, 20);
878                    this.RaiseOnInvalidateRectangle(Rectangle);
879                }
880            }
881
882            //if (Paintables.Contains(entity))
883            //{
884            //    int newpos = Paintables.IndexOf(entity) - zShift;
885            //    //if this is the first in the row you cannot move it lower
886            //    if (newpos >= 0)
887            //    {
888            //        Paintables.Remove(entity);
889            //        Paintables.Insert(newpos, entity);
890            //        ReAssignSceneIndex(Paintables);
891            //        Rectangle rec = entity.Rectangle;
892            //        rec.Inflate(20, 20);
893            //        this.RaiseOnInvalidateRectangle(Rectangle);
894            //    }
895            //}
896        }
897        /// <summary>
898        /// Sends the entity one level down the z-order stack.
899        /// </summary>
900        /// <param name="entity">The entity.</param>
901        public void SendBackwards(IDiagramEntity entity)
902        {
903            SendBackwards(entity, 1);
904        }
905
906        /// <summary>
907        /// Sends the entity to the top of the z-order stack.
908        /// </summary>
909        /// <param name="entity">The entity.</param>
910        public void SendForwards(IDiagramEntity entity)
911        {
912            SendForwards(entity, 1);
913        }
914        /// <summary>
915        /// Sends the entity up the z-order stack with the specified amount.
916        /// </summary>
917        /// <param name="entity">The entity.</param>
918        /// <param name="zShift">The z shift.</param>
919        public void SendForwards(IDiagramEntity entity, int zShift)
920        {
921            ILayer layer = CurrentPage.GetLayer(entity);
922            if (layer != null)
923            {
924                int newpos = layer.Entities.IndexOf(entity) + zShift;
925                //if this is the last in the row you cannot move it higher
926                if (newpos < layer.Entities.Count)
927                {
928                    layer.Entities.Remove(entity);
929                    layer.Entities.Insert(newpos, entity); //does it works when this is an addition at the top?
930                    ReAssignSceneIndex(layer.Entities);
931                    Rectangle rec = entity.Rectangle;
932                    rec.Inflate(20, 20);
933                    this.RaiseOnInvalidateRectangle(Rectangle);
934                }
935            }
936
937            //if (Paintables.Contains(entity) && zShift>=1)
938            //{
939            //    int newpos = Paintables.IndexOf(entity) + zShift;
940            //    //if this is the last in the row you cannot move it higher
941            //    if (newpos < Paintables.Count)
942            //    {
943            //        Paintables.Remove(entity);
944            //        Paintables.Insert(newpos, entity); //does it works when this is an addition at the top?
945            //        ReAssignSceneIndex(Paintables);
946            //        Rectangle rec = entity.Rectangle;
947            //        rec.Inflate(20, 20);
948            //        this.RaiseOnInvalidateRectangle(Rectangle);
949            //    }
950            //}
951        }
952
953        /// <summary>
954        /// Sends the entity to the front of the z-order stack.
955        /// </summary>
956        /// <param name="entity">The entity.</param>
957        public void SendToFront(IDiagramEntity entity)
958        {
959            ILayer layer = CurrentPage.GetLayer(entity);
960            if (layer != null)
961            {
962                layer.Entities.Remove(entity);
963                layer.Entities.Add(entity);
964                ReAssignSceneIndex(layer.Entities);
965                Rectangle rec = entity.Rectangle;
966                rec.Inflate(20, 20);
967                this.RaiseOnInvalidateRectangle(Rectangle);
968            }
969
970            //if(Paintables.Contains(entity))
971            //{
972            //    Paintables.Remove(entity);
973            //    Paintables.Add(entity);
974            //    ReAssignSceneIndex(Paintables);
975            //    Rectangle rec = entity.Rectangle;
976            //    rec.Inflate(20, 20);
977            //    this.RaiseOnInvalidateRectangle(Rectangle);
978            //}
979        }
980        #endregion
981
982        #region Diagram manipulation actions
983
984        // ------------------------------------------------------------------
985        /// <summary>
986        /// Returns the number of shapes in the current page that are of
987        /// the type specified.
988        /// </summary>
989        /// <param name="type">Type</param>
990        /// <returns>int</returns>
991        // ------------------------------------------------------------------
992        public int NumberOfShapes(Type type)
993        {
994            int count = 0;
995            foreach (IShape shape in Shapes)
996            {
997                if (shape.GetType() == type)
998                {
999                    count++;
1000                }
1001            }
1002            return count;
1003        }
1004
1005        // ------------------------------------------------------------------
1006        /// <summary>
1007        /// Gets the shape at the specified location.  If no shape could be
1008        /// found then 'null' is returned.
1009        /// </summary>
1010        /// <param name="surfacePoint">Point: The location in world
1011        /// coordinates.</param>
1012        /// <returns>IShape</returns>
1013        // ------------------------------------------------------------------
1014        public IShape GetShapeAt(Point surfacePoint)
1015        {
1016            foreach (IShape shape in this.CurrentPage.Shapes)
1017            {
1018                if (shape.Hit(surfacePoint))
1019                {
1020                    return shape;
1021                }
1022            }
1023            return null;
1024        }
1025
1026        // ------------------------------------------------------------------
1027        /// <summary>
1028        /// Adds an entity to the diagram.  The magnification level for the
1029        /// entity is set to the current magnification level of the current
1030        /// page.
1031        /// </summary>
1032        /// <param name="entity">IDiagramEntity: The entity to add.</param>
1033        /// <returns>IDiagramEntity: The added entity.</returns>
1034        // ------------------------------------------------------------------
1035        public IDiagramEntity AddEntity(IDiagramEntity entity)
1036        {
1037            SetModel(entity);
1038            //By default the new entity is added to the default layer in the
1039            // current page.
1040            CurrentPage.DefaultLayer.Entities.Add(entity);
1041            entity.Attached(CurrentPage.DefaultLayer);
1042            entity.Magnification = CurrentPage.Magnification;
1043            return entity;
1044        }
1045
1046        // ------------------------------------------------------------------
1047        /// <summary>
1048        /// Adds a shape to the diagram
1049        /// </summary>
1050        /// <param name="shape">IShape: The shape to add.</param>
1051        /// <returns>IShape: The added shape.</returns>
1052        // ------------------------------------------------------------------
1053        public IShape AddShape(IShape shape)
1054        {
1055           
1056            SetModel(shape);
1057            // By default the new shape is added to the default layer in the
1058            // current page.
1059            CurrentPage.DefaultLayer.Entities.Add(shape);
1060            shape.Attached(CurrentPage.DefaultLayer);
1061            shape.ShowConnectors = this.mShowConnectors;
1062            return shape;
1063           
1064        }
1065
1066        // ------------------------------------------------------------------
1067        /// <summary>
1068        /// Adds a connection to the diagram
1069        /// </summary>
1070        /// <param name="connection">a connection</param>
1071        // ------------------------------------------------------------------
1072        public IConnection AddConnection(IConnection connection)
1073        {
1074            SetModel(connection);
1075            CurrentPage.DefaultLayer.Entities.Add(connection);
1076            connection.Attached(CurrentPage.DefaultLayer);
1077            return connection;
1078        }
1079
1080        // ------------------------------------------------------------------
1081        /// <summary>
1082        /// Adds a connection between two shape connectors.       
1083        /// </summary>
1084        /// <param name="from">From connector.</param>
1085        /// <param name="to">To connector.</param>
1086        // ------------------------------------------------------------------
1087        public IConnection AddConnection(IConnector from, IConnector to)
1088        {
1089            Connection con = new Connection(from.Point, to.Point);
1090            this.AddConnection(con);
1091            return con;
1092        }
1093
1094        // ------------------------------------------------------------------
1095        /// <summary>
1096        /// Sets the model (recursively) on the given entity.
1097        /// </summary>
1098        /// <param name="entity">The entity.</param>
1099        // ------------------------------------------------------------------
1100        public void SetModel(IDiagramEntity entity)
1101        {
1102            if(entity is IConnector)
1103            {
1104                (entity as IConnector).Model = this;
1105            }
1106            else if(entity is IConnection)
1107            {
1108                IConnection con = entity as IConnection;
1109                con.Model = this;
1110                Debug.Assert(con.From != null, "The 'From' connector is not set.");
1111                con.From.Model = this;
1112                Debug.Assert(con.From != null, "The 'To' connector is not set.");
1113                con.To.Model = this;
1114            }
1115            else if(entity is IShape)
1116            {
1117                IShape shape = entity as IShape;
1118                shape.Model = this;
1119                foreach(IConnector co in shape.Connectors)
1120                {
1121                    co.Model = this;
1122                }
1123            }
1124            else if (entity is IGroup)
1125            {
1126                IGroup group = entity as IGroup;
1127                group.Model = this;
1128                foreach (IDiagramEntity child in group.Entities)
1129                {
1130                    SetModel(child);
1131                }
1132            }
1133        }
1134
1135        // ------------------------------------------------------------------
1136        /// <summary>
1137        /// Removes the shape from the diagram.
1138        /// </summary>
1139        /// <param name="shape">The shape.</param>
1140        // ------------------------------------------------------------------
1141        public void RemoveShape(IShape shape)
1142        {           
1143            //remove it from the layer(s)
1144            foreach (IPage page in mPages)
1145            {
1146                foreach (ILayer layer in page.Layers)
1147                {
1148                    if (layer.Entities.Contains(shape))
1149                    {
1150                        layer.Entities.Remove(shape);
1151                        shape.Detached(CurrentPage.DefaultLayer);                       
1152                    }
1153                }
1154            }
1155
1156            // The old way, when there weren't multiple pages and layers.
1157            //if (CurrentPage.DefaultLayer.Entities.Contains(shape))
1158            //{
1159            //    CurrentPage.DefaultLayer.Entities.Remove(shape);
1160            //    shape.Detached(CurrentPage.DefaultLayer);
1161            //}
1162        }
1163
1164        // ------------------------------------------------------------------
1165        /// <summary>
1166        /// Removes all entities that are currently selected.
1167        /// </summary>
1168        /// <param name="entity">The entity.</param>
1169        // ------------------------------------------------------------------
1170        public void RemoveSelectedItems()
1171        {
1172            if (this.Selection.SelectedItems.Count < 1)
1173            {
1174                return;
1175            }
1176
1177            int numberOfItems = this.Selection.SelectedItems.Count;
1178            for (int i = 0; i < numberOfItems - 1; i++)
1179            {
1180                IDiagramEntity entity = Selection.SelectedItems[0];
1181                foreach (IPage page in mPages)
1182                {
1183                    foreach (ILayer layer in page.Layers)
1184                    {
1185                        if (layer.Entities.Contains(entity))
1186                        {
1187                            layer.Entities.Remove(entity);
1188                            entity.Detached(DefaultPage.DefaultLayer);
1189                        }
1190                    }
1191                }
1192            }
1193        }
1194
1195        // ------------------------------------------------------------------
1196        /// <summary>
1197        /// Removes the specified entity.
1198        /// </summary>
1199        /// <param name="entity">The entity.</param>
1200        // ------------------------------------------------------------------
1201        public void Remove(IDiagramEntity entity)
1202        {
1203            if (CurrentPage.DefaultLayer.Entities.Contains(entity))
1204            {
1205                CurrentPage.DefaultLayer.Entities.Remove(entity);
1206                entity.Detached(CurrentPage.DefaultLayer);
1207            }
1208        }
1209
1210        // ------------------------------------------------------------------
1211        /// <summary>
1212        /// Adds a collection of entities to the diagram
1213        /// </summary>
1214        /// <param name="collection">The collection.</param>
1215        // ------------------------------------------------------------------
1216        public void AddEntities(CollectionBase<IDiagramEntity> collection)
1217        {
1218            foreach (IDiagramEntity entity in collection)
1219            {
1220                SetModel(entity);
1221                CurrentPage.DefaultLayer.Entities.Add(entity);
1222                entity.Attached(CurrentPage.DefaultLayer);               
1223            }
1224        }
1225
1226        // ------------------------------------------------------------------
1227        /// <summary>
1228        /// Unwraps an entity
1229        /// <list type="bullet">
1230        /// <term>Uid</term><description>Generates a new <see cref="IDiagramEntity.Uid"/> for the entity. </description>
1231        /// <tem>Model</tem><description>Assigns the Model property to the entity.</description>
1232        ///
1233        /// </list>
1234        /// </summary>
1235        // ------------------------------------------------------------------
1236        public void Unwrap(IDiagramEntity entity)
1237        {
1238            //set a new unique identifier for this copied object
1239            entity.NewUid(true);
1240            //this assignment will be recursive if needed
1241            SetModel(entity);
1242            CurrentPage.DefaultLayer.Entities.Add(entity);
1243            entity.Attached(CurrentPage.DefaultLayer);
1244           
1245        }
1246
1247        // ------------------------------------------------------------------
1248        /// <summary>
1249        /// Unwraps the specified collection.
1250        /// </summary>
1251        /// <param name="collection">The collection.</param>
1252        // ------------------------------------------------------------------
1253        public void Unwrap(CollectionBase<IDiagramEntity> collection)
1254        {
1255            if (collection == null)
1256                return;
1257            foreach (IDiagramEntity entity in collection)
1258            {
1259                Unwrap(entity);
1260            }
1261            //reconnect the connectors, just like the deserialization of a filed diagram
1262            Dictionary<Guid, Anchor>.Enumerator enumer = Anchors.GetEnumerator();
1263            System.Collections.Generic.KeyValuePair<Guid, Anchor> pair;
1264            Anchor anchor;
1265            while (enumer.MoveNext())
1266            {
1267                pair = enumer.Current;
1268                anchor = pair.Value;
1269                if (anchor.Parent != Guid.Empty) //there's a parent connector
1270                {
1271                    if (Anchors.ContainsKey(anchor.Parent))
1272                    {
1273                        Anchors.GetAnchor(anchor.Parent).Instance.AttachConnector(anchor.Instance);
1274                    }
1275                }
1276            }
1277            //clean up the anchoring matrix
1278            Anchors.Clear();
1279        }
1280
1281        // ------------------------------------------------------------------
1282        /// <summary>
1283        /// Clears the current page.
1284        /// </summary>
1285        // ------------------------------------------------------------------
1286        public void Clear()
1287        {
1288            //clear the scene-graph
1289            this.CurrentPage.DefaultLayer.Entities.Clear();
1290        }
1291        #endregion
1292     
1293        #endregion
1294
1295        #region Standard IDispose implementation
1296
1297        // ------------------------------------------------------------------
1298        /// <summary>
1299        /// Disposes the view.
1300        /// </summary>
1301        // ------------------------------------------------------------------
1302        public void Dispose()
1303        {
1304            Dispose(true);
1305            GC.SuppressFinalize(this);
1306        }
1307
1308        // ------------------------------------------------------------------
1309        /// <summary>
1310        /// Disposes the view.
1311        /// </summary>
1312        /// <param name="disposing">if set to <c>true</c> [disposing].</param>
1313        // ------------------------------------------------------------------
1314        private void Dispose(bool disposing)
1315        {
1316            if (disposing)
1317            {
1318               
1319            }
1320
1321        }
1322
1323        #endregion
1324    }
1325}
Note: See TracBrowser for help on using the repository browser.