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 @ 2768

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

added solution folders and sources for the netron library (ticket #867)

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