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/ControllerBase.cs @ 3355

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

adapted OperatorGraphView to readyonly mechanism (ticket #973)

File size: 51.2 KB
Line 
1using System;
2using System.Drawing;
3using System.Collections.Generic;
4using System.Text;
5using System.Windows.Forms;
6using System.ComponentModel;
7using System.Diagnostics;
8namespace Netron.Diagramming.Core {
9  // ----------------------------------------------------------------------
10  /// <summary>
11  /// Abstract base implementation of the <see cref="IController"/>
12  /// interface.
13  /// </summary>
14  // ----------------------------------------------------------------------
15  public abstract class ControllerBase : IUndoSupport, IController {
16    #region Events
17
18    // ------------------------------------------------------------------
19    /// <summary>
20    /// Occurs when the context menu is shown.
21    /// </summary>
22    // ------------------------------------------------------------------
23    public event EventHandler<EntityMenuEventArgs> OnShowContextMenu;
24
25    // ------------------------------------------------------------------
26    /// <summary>
27    /// Occurs when a tool is asked to be deactivated.
28    /// </summary>
29    // ------------------------------------------------------------------
30    public event EventHandler<ToolEventArgs> OnToolDeactivate;
31
32    // ------------------------------------------------------------------
33    /// <summary>
34    /// Occurs when a tool is asked to be activated.
35    /// </summary>
36    // ------------------------------------------------------------------
37    public event EventHandler<ToolEventArgs> OnToolActivate;
38
39    // ------------------------------------------------------------------
40    /// <summary>
41    /// Occurs when the history has changed in the undo/redo mechanism.
42    /// </summary>
43    // ------------------------------------------------------------------
44    public event EventHandler<HistoryChangeEventArgs> OnHistoryChange;
45
46    // ------------------------------------------------------------------
47    /// <summary>
48    /// Occurs when the something got selected and the properties of it
49    /// can/should be shown.
50    /// </summary>
51    // ------------------------------------------------------------------
52    public event EventHandler<SelectionEventArgs> OnShowSelectionProperties;
53
54    // ------------------------------------------------------------------
55    /// <summary>
56    /// Occurs when an entity is added.
57    /// <remarks>This event usually is bubbled from one of the
58    /// layers.</remarks>
59    /// </summary>
60    // ------------------------------------------------------------------
61    public event EventHandler<EntityEventArgs> OnEntityAdded;
62
63    // ------------------------------------------------------------------
64    /// <summary>
65    /// Occurs when an entity is removed.
66    /// <remarks>This event usually is bubbled from one of the
67    /// layers.</remarks>
68    /// </summary>
69    // ------------------------------------------------------------------
70    public event EventHandler<EntityEventArgs> OnEntityRemoved;
71
72    // ------------------------------------------------------------------
73    /// <summary>
74    /// Occurs when the controller receives a mouse-down notification of
75    /// the surface. This event is raised before the
76    /// event is broadcasted down to the tools.
77    /// </summary>
78    // ------------------------------------------------------------------
79    public event EventHandler<MouseEventArgs> OnMouseDown;
80
81    // ------------------------------------------------------------------
82    /// <summary>
83    /// Occurs when the Ambience has changed.
84    /// </summary>
85    // ------------------------------------------------------------------
86    public event EventHandler<AmbienceEventArgs> OnAmbienceChanged;
87
88
89    #endregion
90
91    #region Tool Names
92
93    public const string AlignBottomEdgesToolName =
94        "Align Bottom Edges Tool";
95
96    public const string AlignCentersHorizToolName =
97        "Align Centers Horizontally";
98
99    public const string AlignCentersVertToolName =
100        "Align Centers Vertically";
101
102    public const string AlignLeftEdgesToolName =
103        "Align Left Edges Tool";
104
105    public const string AlignRightEdgesToolName =
106        "Align Right Edges Tool";
107
108    public const string AlignTopEdgesToolName =
109        "Align Top Edges Tool";
110
111    public const string ComplexRectangleToolName = "ComplexRectangle Tool";
112    public const string ConnectionToolName = "Connection Tool";
113    public const string ConnectorMoverToolName = "Connector Mover Tool";
114    public const string ContextToolName = "Context Tool";
115    public const string CopyToolName = "Copy Tool";
116    public const string CutToolName = "Cut Tool";
117    public const string DeleteToolName = "Delete Tool";
118    public const string DragDropToolName = "DragDrop Tool";
119    public const string EllipseToolName = "Ellipse Tool";
120    public const string GroupToolName = "Group Tool";
121    public const string HitToolName = "Hit Tool";
122    public const string HoverToolName = "Hover Tool";
123    public const string ImageExportToolName = "Image Export Tool";
124    public const string MoveToolName = "Move Tool";
125    public const string MultiLineToolName = "MultiLine Tool";
126    public const string PanToolName = "Pan Tool";
127    public const string PasteToolName = "Paste Tool";
128    public const string PolygonToolName = "Polygon Tool";
129    public const string RectangleToolName = "Rectangle Tool";
130    public const string ScribbleToolName = "Scribble Tool";
131    public const string SelectionToolName = "Selection Tool";
132    public const string SendBackwardsToolName = "SendBackwards Tool";
133    public const string SendForwardsToolName = "SendForwards Tool";
134    public const string SendToBackToolName = "SendToBack Tool";
135    public const string SendToFrontToolName = "SendToFront Tool";
136    public const string TransformToolName = "Transform Tool";
137    public const string UngroupToolName = "Ungroup Tool";
138    public const string ZoomAreaToolName = "Zoom Area Tool";
139    public const string ZoomInToolName = "Zoom In Tool";
140    public const string ZoomOutToolName = "Zoom Out Tool";
141
142    #endregion
143
144    #region Fields
145
146    private bool eventsEnabled = true;
147    private bool controllerEnabled = true;
148
149    private IModel mModel;
150    private UndoManager mUndoManager;
151    ITool activeTool;
152
153    /// <summary>
154    /// the View field
155    /// </summary>
156    private IView mView;
157    protected CollectionBase<IMouseListener> mouseListeners;
158    protected CollectionBase<IKeyboardListener> keyboardListeners;
159    protected CollectionBase<IDragDropListener> dragdropListeners;
160    protected IDiagramControl parentControl;
161    protected CollectionBase<ITool> registeredTools;
162    protected CollectionBase<IActivity> registeredActivity;
163
164    #endregion
165
166    #region Properties
167
168    /// <summary>
169    /// Gets or sets a value indicating whether this <see cref="T:ControllerBase"/> is enabled.
170    /// </summary>
171    /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
172    public bool Enabled {
173      get {
174        return controllerEnabled;
175      }
176      set {
177        controllerEnabled = value;
178      }
179    }
180
181    // ------------------------------------------------------------------
182    /// <summary>
183    /// Gets the currently active tool.  This can be 'null'!!!
184    /// </summary>
185    // ------------------------------------------------------------------
186    public ITool ActiveTool {
187      get {
188        return this.activeTool;
189      }
190    }
191
192    /// <summary>
193    /// Gets or sets the parent control.
194    /// </summary>
195    /// <value>The parent control.</value>
196    public IDiagramControl ParentControl {
197      get { return parentControl; }
198      internal set { parentControl = value; }
199    }
200    /// <summary>
201    /// Gets the registered tools.
202    /// </summary>
203    /// <value>The tools.</value>
204    public CollectionBase<ITool> Tools {
205      get { return registeredTools; }
206    }
207
208
209
210    /// <summary>
211    /// Gets the undo manager.
212    /// </summary>
213    /// <value>The undo manager.</value>
214    public UndoManager UndoManager {
215      get {
216        return mUndoManager;
217      }
218
219    }
220
221    /// <summary>
222    /// Gets or sets the model
223    /// </summary>
224    /// <value></value>
225    public IModel Model {
226      get {
227        return mModel;
228      }
229      set {
230        AttachToModel(value);
231      }
232    }
233
234    /// <summary>
235    /// Gets or sets the view.
236    /// </summary>
237    /// <value>The view.</value>
238    public IView View {
239      get {
240        return mView;
241      }
242      set {
243        AttachToView(value);
244      }
245    }
246
247    /// <summary>
248    /// Attaches to the given view.
249    /// </summary>
250    /// <param name="view">The view.</param>
251    private void AttachToView(IView view) {
252      if (view == null)
253        throw new ArgumentNullException();
254
255      mView = view;
256    }
257    #endregion
258
259    #region Constructor
260
261    // ------------------------------------------------------------------
262    /// <summary>
263    /// Default constructor.
264    /// </summary>
265    // ------------------------------------------------------------------
266    protected ControllerBase(IDiagramControl surface) {
267      //doesn't work if you supply a null reference
268      if (surface == null) {
269        throw new NullReferenceException(
270            "The diagram control assigned to the controller " +
271            "cannot be 'null'");
272      }
273
274      //create the undo/redo manager
275      mUndoManager = new UndoManager(15);
276      mUndoManager.OnHistoryChange += new EventHandler(
277          mUndoManager_OnHistoryChange);
278
279      #region Instantiation of listeners
280      mouseListeners = new CollectionBase<IMouseListener>();
281      keyboardListeners = new CollectionBase<IKeyboardListener>();
282      dragdropListeners = new CollectionBase<IDragDropListener>();
283      #endregion
284
285      //keep a reference to the parent control
286      parentControl = surface;
287
288      AttachToSurface(parentControl);
289
290
291
292      //Initialize the colorscheme
293      ArtPalette.Init();
294
295      #region Tools: the registration order matters!
296      /*
297             The order in in which the tools are added matters, at least
298             some of them.
299               * The TransformTool should come before the HitTool and the
300                 MoveTool after the HitTool.
301               * The order of the drawing tools does not matter.
302               * It's also important to remark that the tools do not depend
303                 on the Model.
304             */
305
306      registeredTools = new CollectionBase<ITool>();
307
308      this.AddTool(new TransformTool(TransformToolName));
309
310      this.AddTool(new HitTool(HitToolName));
311
312      this.AddTool(new MoveTool(MoveToolName));
313
314      this.AddTool(new RectangleTool(RectangleToolName));
315
316      this.AddTool(new ComplexRectangleTool(ComplexRectangleToolName));
317
318      this.AddTool(new EllipseTool(EllipseToolName));
319
320      this.AddTool(new SelectionTool(SelectionToolName));
321
322      this.AddTool(new DragDropTool(DragDropToolName));
323
324      this.AddTool(new ConnectionTool(ConnectionToolName));
325
326      this.AddTool(new ConnectorMoverTool(ConnectorMoverToolName));
327
328      this.AddTool(new GroupTool(GroupToolName));
329
330      this.AddTool(new UngroupTool(UngroupToolName));
331
332      this.AddTool(new SendToBackTool(SendToBackToolName));
333
334      this.AddTool(new SendBackwardsTool(SendBackwardsToolName));
335
336      this.AddTool(new SendForwardsTool(SendForwardsToolName));
337
338      this.AddTool(new SendToFrontTool(SendToFrontToolName));
339
340      this.AddTool(new HoverTool(HoverToolName));
341
342      this.AddTool(new ContextTool(ContextToolName));
343
344      this.AddTool(new CopyTool(CopyToolName));
345
346      this.AddTool(new CutTool(CutToolName));
347
348      this.AddTool(new PasteTool(PasteToolName));
349
350      this.AddTool(new DeleteTool(DeleteToolName));
351
352      this.AddTool(new ScribbleTool(ScribbleToolName));
353
354      this.AddTool(new PolygonTool(PolygonToolName));
355
356      this.AddTool(new MultiLineTool(MultiLineToolName));
357
358      this.AddTool(new AlignBottomEdgesTool(AlignBottomEdgesToolName));
359
360      this.AddTool(
361          new AlignCentersHorizontallyTool(AlignCentersHorizToolName));
362
363      this.AddTool(
364          new AlignCentersVerticallyTool(AlignCentersVertToolName));
365
366      this.AddTool(new AlignLeftEdgesTool(AlignLeftEdgesToolName));
367
368      this.AddTool(new AlignRightEdgesTool(AlignRightEdgesToolName));
369
370      this.AddTool(new AlignTopEdgesTool(AlignTopEdgesToolName));
371
372      this.AddTool(new ZoomAreaTool(ZoomAreaToolName));
373
374      this.AddTool(new ZoomInTool(ZoomInToolName));
375
376      this.AddTool(new ZoomOutTool(ZoomOutToolName));
377
378      this.AddTool(new PanTool(PanToolName));
379
380      this.AddTool(new ImageExportTool(ImageExportToolName));
381
382      #endregion
383
384      #region Hotkeys
385      HotKeys keys = new HotKeys(this);
386      this.keyboardListeners.Add(keys);
387      #endregion
388
389      #region Activities
390      // This is in a way a waste of memory; the layouts should not
391      // necessarily be loaded before they are actually requested.
392      // You could register only the (string) names instead.
393      // But for just a few algorithms this is OK and the advantage
394      // of this registration is that one can register actions from
395      // outside the library, in the hosting form for example.
396      registeredActivity = new CollectionBase<IActivity>();
397      AddActivity(new RandomLayout(this));
398      AddActivity(new FruchtermanReingoldLayout(this));
399      AddActivity(new StandardTreeLayout(this));
400      AddActivity(new RadialTreeLayout(this));
401      AddActivity(new BalloonTreeLayout(this));
402      AddActivity(new ForceDirectedLayout(this));
403      #endregion
404    }
405
406    #endregion
407
408    // ------------------------------------------------------------------
409    /// <summary>
410    /// Attaches the given model to the controller.
411    /// </summary>
412    /// <param name="model">IModel</param>
413    // ------------------------------------------------------------------
414    protected virtual void AttachToModel(IModel model) {
415      if (model == null)
416        throw new ArgumentNullException();
417
418      mModel = model;
419      mModel.OnEntityAdded +=
420          new EventHandler<EntityEventArgs>(mModel_OnEntityAdded);
421      mModel.OnEntityRemoved +=
422          new EventHandler<EntityEventArgs>(mModel_OnEntityRemoved);
423      mModel.OnAmbienceChanged +=
424          new EventHandler<AmbienceEventArgs>(mModel_OnAmbienceChanged);
425    }
426
427    // ------------------------------------------------------------------
428    /// <summary>
429    /// Passes the OnAmbienceChanged event on.
430    /// </summary>
431    /// <param name="sender">object</param>
432    /// <param name="e">AmbienceEventArgs</param>
433    // ------------------------------------------------------------------
434    void mModel_OnAmbienceChanged(
435        object sender,
436        AmbienceEventArgs e) {
437      RaiseOnAmbienceChanged(e);
438    }
439
440    // ------------------------------------------------------------------
441    /// <summary>
442    /// Passes the OnEntityRemoved event on.
443    /// </summary>
444    /// <param name="sender">object</param>
445    /// <param name="e">EntityEventArgs</param>
446    // ------------------------------------------------------------------
447    void mModel_OnEntityRemoved(
448        object sender,
449        EntityEventArgs e) {
450      RaiseOnEntityRemoved(e);
451    }
452
453    // ------------------------------------------------------------------
454    /// <summary>
455    /// Passes the OnEntityAdded event on.
456    /// </summary>
457    /// <param name="sender">object</param>
458    /// <param name="e">EntityEventArgs</param>
459    // ------------------------------------------------------------------
460    void mModel_OnEntityAdded(
461        object sender,
462        EntityEventArgs e) {
463      RaiseOnEntityAdded(e);
464    }
465
466    // ------------------------------------------------------------------
467    /// <summary>
468    /// Bubbles the OnHistoryChange event.
469    /// </summary>
470    /// <param name="sender">The source of the event.</param>
471    /// <param name="e">The <see cref="T:System.EventArgs"/> instance
472    /// containing the event data.</param>
473    // ------------------------------------------------------------------
474    void mUndoManager_OnHistoryChange(object sender, EventArgs e) {
475      RaiseOnHistoryChange();
476    }
477
478    #region Methods
479
480    // ------------------------------------------------------------------
481    /// <summary>
482    /// Activates the text editor for the given text provider.
483    /// </summary>
484    /// <param name="textProvider">ITextProvider</param>
485    /// <returns>bool: True if sucessful, false if not.</returns>
486    // ------------------------------------------------------------------
487    public abstract bool ActivateTextEditor(ITextProvider textProvider);
488
489    // ------------------------------------------------------------------
490    /// <summary>
491    /// Changes the paint style of the selected entities.
492    /// </summary>
493    /// <param name="paintStyle">IPaintStyle</param>
494    // ------------------------------------------------------------------
495    public void ChangeStyle(IPaintStyle paintStyle) {
496
497      // Note that you need a copy of the selected item otherwise the
498      // undo/redo will fail once the selection has changed
499      FillStyleCommand cmd = new FillStyleCommand(
500          this,
501          this.Model.Selection.SelectedItems.Copy(),
502          paintStyle);
503
504      this.UndoManager.AddUndoCommand(cmd);
505      cmd.Redo();
506    }
507
508    // ------------------------------------------------------------------
509    /// <summary>
510    /// Changes the pen style  of the selected entities.
511    /// </summary>
512    /// <param name="penStyle">The pen style.</param>
513    // ------------------------------------------------------------------
514    public void ChangeStyle(IPenStyle penStyle) {
515      PenStyleCommand cmd = new PenStyleCommand(
516          this,
517          this.Model.Selection.SelectedItems.Copy(),
518          penStyle);
519
520      this.UndoManager.AddUndoCommand(cmd);
521
522      cmd.Redo();
523    }
524
525    #region Event Raisers
526
527    // ------------------------------------------------------------------
528    /// <summary>
529    /// Raises the OnShowContextMenu event
530    /// </summary>
531    /// <param name="e">EntityMenuEventArgs</param>
532    // ------------------------------------------------------------------
533    public virtual void RaiseOnShowContextMenu(EntityMenuEventArgs e) {
534      EventHandler<EntityMenuEventArgs> handler = OnShowContextMenu;
535      if (handler != null) {
536        handler(this, e);
537      }
538    }
539
540    // ------------------------------------------------------------------
541    /// <summary>
542    /// Raises the OnHistory change.
543    /// </summary>
544    // ------------------------------------------------------------------
545    public virtual void RaiseOnHistoryChange() {
546      EventHandler<HistoryChangeEventArgs> handler = OnHistoryChange;
547      if (handler != null) {
548        handler(this, new HistoryChangeEventArgs(
549            this.UndoManager.RedoText,
550            this.UndoManager.UndoText));
551      }
552    }
553
554    // ------------------------------------------------------------------
555    /// <summary>
556    /// Raises the <see cref="OnToolDeactivate"/> event.
557    /// </summary>
558    /// <param name="e">ConnectionCollection event argument</param>
559    // ------------------------------------------------------------------
560    public virtual void RaiseOnToolDeactivate(ToolEventArgs e) {
561      EventHandler<ToolEventArgs> handler = OnToolDeactivate;
562      if (handler != null) {
563        handler(this, e);
564      }
565    }
566
567    // ------------------------------------------------------------------
568    /// <summary>
569    /// Raises the <see cref="OnToolActivate"/> event
570    /// </summary>
571    /// <param name="e">ConnectionCollection event argument</param>
572    // ------------------------------------------------------------------
573    public virtual void RaiseOnToolActivate(ToolEventArgs e) {
574      EventHandler<ToolEventArgs> handler = OnToolActivate;
575      if (handler != null) {
576        handler(this, e);
577      }
578    }
579
580    // ------------------------------------------------------------------
581    /// <summary>
582    /// Raises the OnShowSelectionProperties event.
583    /// </summary>
584    /// <param name="e">The
585    /// <see cref="T:Netron.Diagramming.Core.SelectionEventArgs"/>
586    /// instance containing the event data.</param>
587    // ------------------------------------------------------------------
588    public virtual void RaiseOnShowSelectionProperties(SelectionEventArgs e) {
589      EventHandler<SelectionEventArgs> handler = OnShowSelectionProperties;
590      if (handler != null) {
591        handler(this, e);
592      }
593    }
594
595    // ------------------------------------------------------------------
596    /// <summary>
597    /// Raises the <see cref="OnMouseDown "/> event.
598    /// </summary>
599    /// <param name="e">The
600    /// <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance
601    /// containing the event data.</param>
602    // ------------------------------------------------------------------
603    protected virtual void RaiseOnMouseDown(MouseEventArgs e) {
604      if (OnMouseDown != null)
605        OnMouseDown(this, e);
606    }
607
608    // ------------------------------------------------------------------
609    /// <summary>
610    /// Raises the <see cref="OnEntityAdded"/> event.
611    /// </summary>
612    /// <param name="e">The
613    /// <see cref="T:Netron.Diagramming.Core.EntityEventArgs"/> instance
614    /// containing the event data.</param>
615    // ------------------------------------------------------------------
616    protected virtual void RaiseOnEntityAdded(EntityEventArgs e) {
617      EventHandler<EntityEventArgs> handler = OnEntityAdded;
618      if (handler != null) {
619        handler(this, e);
620      }
621    }
622
623    // ------------------------------------------------------------------
624    /// <summary>
625    /// Raises the <see cref="OnEntityRemoved"/> event.
626    /// </summary>
627    /// <param name="e">The
628    /// <see cref="T:Netron.Diagramming.Core.EntityEventArgs"/> instance
629    /// containing the event data.</param>
630    // ------------------------------------------------------------------
631    protected virtual void RaiseOnEntityRemoved(EntityEventArgs e) {
632      EventHandler<EntityEventArgs> handler = OnEntityRemoved;
633      if (handler != null) {
634        handler(this, e);
635      }
636    }
637
638    // ------------------------------------------------------------------
639    /// <summary>
640    /// Raises the <see cref="OnAmbienceChanged"/> event.
641    /// </summary>
642    /// <param name="e">AmbienceEventArgs</param>
643    // ------------------------------------------------------------------
644    protected virtual void RaiseOnAmbienceChanged(AmbienceEventArgs e) {
645      EventHandler<AmbienceEventArgs> handler = OnAmbienceChanged;
646      if (handler != null) {
647        handler(this, e);
648      }
649    }
650
651    #endregion
652
653    #region Tool (de)activation methods
654
655    // ------------------------------------------------------------------
656    /// <summary>
657    /// Deactivates the given tool.
658    /// </summary>
659    /// <param name="tool">a registered ITool</param>
660    /// <returns>bool: True if successful.</returns>
661    // ------------------------------------------------------------------
662    public bool DeactivateTool(ITool tool) {
663      bool flag = false;
664      if (tool != null && tool.Enabled && tool.IsActive) {
665        //IEnumerator iEnumerator = tools.GetEnumerator();
666        //Tool tool2 = null;
667        //while (iEnumerator.MoveNext())
668        //{
669        //    tool2 = iEnumerator.Current is Tool;
670        //    if (tool2 != null && tool2 != tool)
671        //    {
672        //        tool2.ToolDeactivating(tool);
673        //    }
674        //}
675        flag = tool.DeactivateTool();
676        if (flag && eventsEnabled) {
677          RaiseOnToolDeactivate(new ToolEventArgs(tool));
678        }
679      }
680      return flag;
681    }
682
683    // ------------------------------------------------------------------
684    /// <summary>
685    /// Deactivates all tools.
686    /// </summary>
687    /// <returns>bool: True if successful.</returns>
688    // ------------------------------------------------------------------
689    public bool DeactivateAllTools() {
690      bool successful = true;
691
692      // If the deactivation of any tool returns false, then we will
693      // return false.
694      foreach (ITool tool in this.Tools) {
695        successful = successful & this.DeactivateTool(tool);
696      }
697      this.activeTool = null;
698      return successful;
699    }
700
701    // ------------------------------------------------------------------
702    /// <summary>
703    /// Activates the tool with the given name
704    /// </summary>
705    /// <param name="toolName"></param>
706    // ------------------------------------------------------------------
707    public void ActivateTool(string toolName) {
708      if (!controllerEnabled)
709        return;
710
711      //using anonymous method here
712      Predicate<ITool> predicate = delegate(ITool tool) {
713        if (tool.Name.ToLower() == toolName.ToLower())//not case sensitive
714          return true;
715        else
716          return false;
717      };
718
719      // First deactivate the current tool.
720      if (this.activeTool != null) {
721        this.activeTool.DeactivateTool();
722      }
723      ITool foundTool = this.registeredTools.Find(predicate);
724      ActivateTool(foundTool);
725    }
726
727    // ------------------------------------------------------------------
728    /// <summary>
729    /// Suspends all tools
730    /// </summary>
731    // ------------------------------------------------------------------
732    public void SuspendAllTools() {
733      foreach (ITool tool in this.Tools) {
734        tool.IsSuspended = true;
735      }
736    }
737
738    // ------------------------------------------------------------------
739    /// <summary>
740    /// Unsuspends all tools.
741    /// </summary>
742    // ------------------------------------------------------------------
743    public void UnsuspendAllTools() {
744      foreach (ITool tool in this.Tools) {
745        tool.IsSuspended = false;
746      }
747    }
748
749    // ------------------------------------------------------------------
750    /// <summary>
751    /// Activates a registered tool
752    /// </summary>
753    /// <param name="tool">a registered ITool</param>
754    /// <returns>bool: Returns if the activation was successful.  True is
755    /// returned if it was, false if not.</returns>
756    // ------------------------------------------------------------------
757    private bool ActivateTool(ITool tool) {
758      if (!controllerEnabled)
759        return false;
760      bool flag = false;
761      if (tool != null && tool.CanActivate) {
762        flag = tool.ActivateTool();
763        this.activeTool = tool;
764        if (flag && eventsEnabled) {
765          RaiseOnToolActivate(new ToolEventArgs(tool));
766        }
767      }
768      return flag;
769    }
770
771    #endregion
772
773    // ------------------------------------------------------------------
774    /// <summary>
775    /// Adds the given tool.
776    /// </summary>
777    /// <param name="tool">The tool.</param>
778    // ------------------------------------------------------------------
779    public void AddTool(ITool tool) {
780      tool.Controller = this;
781      // Add the tool to the collection even if it doesn't attach to
782      // anything (yet)
783      registeredTools.Add(tool);
784
785      IMouseListener mouseTool = null;
786      if ((mouseTool = tool as IMouseListener) != null)
787        mouseListeners.Add(mouseTool);
788
789      IKeyboardListener keyboardTool = null;
790      if ((keyboardTool = tool as IKeyboardListener) != null)
791        keyboardListeners.Add(keyboardTool);
792
793      IDragDropListener dragdropTool = null;
794      if ((dragdropTool = tool as IDragDropListener) != null)
795        dragdropListeners.Add(dragdropTool);
796
797      // Watch when the tool is (de)activated so we can pass it on.
798      tool.OnToolActivate +=
799          new EventHandler<ToolEventArgs>(AddedTool_OnToolActivate);
800
801      tool.OnToolDeactivate +=
802          new EventHandler<ToolEventArgs>(AddedTool_OnToolDeactivate);
803    }
804
805    // ------------------------------------------------------------------
806    /// <summary>
807    /// Called when an added tool is deactivated.  The event is passed on
808    /// by calling RaiseOnToolDeactivate.
809    /// </summary>
810    /// <param name="sender">object</param>
811    /// <param name="e">ToolEventArgs</param>
812    // ------------------------------------------------------------------
813    protected void AddedTool_OnToolDeactivate(object sender, ToolEventArgs e) {
814      ITool nextActiveToolInList = null;
815      if (this.activeTool == e.Properties) {
816        foreach (ITool tool in this.Tools) {
817          if (tool.IsActive) {
818            nextActiveToolInList = tool;
819            break;
820          }
821        }
822        activeTool = nextActiveToolInList;
823      }
824      this.RaiseOnToolDeactivate(e);
825    }
826
827    // ------------------------------------------------------------------
828    /// <summary>
829    /// Called when an added tool is activated.  The event is passed on
830    /// by calling RaiseOnToolActivate.
831    /// </summary>
832    /// <param name="sender">object</param>
833    /// <param name="e">ToolEventArgs</param>
834    // ------------------------------------------------------------------
835    protected void AddedTool_OnToolActivate(object sender, ToolEventArgs e) {
836      this.RaiseOnToolActivate(e);
837    }
838
839    #region Activity
840
841    // ------------------------------------------------------------------
842    /// <summary>
843    /// Adds the given activity to the controller.
844    /// </summary>
845    /// <param name="activity">The activity.</param>
846    // ------------------------------------------------------------------
847    public void AddActivity(IActivity activity) {
848
849      registeredActivity.Add(activity);
850    }
851
852    // ------------------------------------------------------------------
853    /// <summary>
854    /// Runs the given activity.
855    /// </summary>
856    /// <param name="activity">The activity.</param>
857    // ------------------------------------------------------------------
858    protected void RunActivity(IActivity activity) {
859      if (activity == null) return;
860      PrepareActivity(activity);
861
862      activity.Run();
863
864    }
865
866    // ------------------------------------------------------------------
867    /// <summary>
868    /// Runs the given activity.
869    /// </summary>
870    /// <param name="activity">The activity.</param>
871    /// <param name="milliseconds">The milliseconds.</param>
872    // ------------------------------------------------------------------
873    protected void RunActivity(IActivity activity, int milliseconds) {
874      if (activity == null) return;
875      PrepareActivity(activity);
876      activity.Run(milliseconds);
877    }
878
879    // ------------------------------------------------------------------
880    /// <summary>
881    /// Prepares the activity.
882    /// </summary>
883    /// <param name="activity">The activity.</param>
884    // ------------------------------------------------------------------
885    private void PrepareActivity(IActivity activity) {
886      if (activity is IAction)
887        (activity as IAction).Model = this.Model;
888      if (activity is ILayout) {
889        (activity as ILayout).Bounds = parentControl.ClientRectangle;
890        (activity as ILayout).Center = new PointF(parentControl.ClientRectangle.Width / 2, parentControl.ClientRectangle.Height / 2);
891      }
892    }
893
894    // ------------------------------------------------------------------
895    /// <summary>
896    /// Runs the activity with the name specified.  If no activity could
897    /// by found with the given name then an exception is thrown.
898    /// </summary>
899    /// <param name="activityName">string: The name of the
900    /// activity to run.</param>
901    // ------------------------------------------------------------------
902    public void RunActivity(string activityName) {
903      if (!controllerEnabled)
904        return;
905
906      this.View.CurrentCursor = Cursors.WaitCursor;
907      controllerEnabled = false;
908
909      IActivity foundActivity = FindActivity(activityName);
910      if (foundActivity != null) {
911        RunActivity(foundActivity);
912      }
913
914      controllerEnabled = true;
915      this.View.CurrentCursor = Cursors.Default;
916
917      // After returning the canvas back to "normal", if the activity
918      // wasn't found throw an exception (as specified by IController).
919      if (foundActivity == null) {
920        throw new Exception("Activity '" + activityName +
921            "' could not be found.");
922      }
923    }
924
925    // ------------------------------------------------------------------
926    /// <summary>
927    /// Finds the activity with the given name.
928    /// </summary>
929    /// <param name="name">The name.</param>
930    /// <returns>IActivity</returns>
931    // ------------------------------------------------------------------
932    protected IActivity FindActivity(string name) {
933      //using anonymous method here
934      Predicate<IActivity> predicate = delegate(IActivity activity) {
935        if (activity.Name.ToLower() == name.ToLower())//not case sensitive
936          return true;
937        else
938          return false;
939      };
940      return this.registeredActivity.Find(predicate);
941
942    }
943
944    // ------------------------------------------------------------------
945    /// <summary>
946    /// Runs the given activity for the specified time span.
947    /// </summary>
948    /// <param name="name">The name.</param>
949    /// <param name="milliseconds">The milliseconds.</param>
950    // ------------------------------------------------------------------
951    public void RunActivity(string name, int milliseconds) {
952      if (!controllerEnabled)
953        return;
954
955      IActivity foundActivity = FindActivity(name);
956      if (foundActivity != null)
957        RunActivity(foundActivity, milliseconds);
958    }
959
960    #endregion
961
962    // ------------------------------------------------------------------
963    /// <summary>
964    /// Attaches this controller to the surface.
965    /// </summary>
966    /// <param name="surface">The surface.</param>
967    // ------------------------------------------------------------------
968    protected virtual void AttachToSurface(IDiagramControl surface) {
969      #region Mouse events
970      surface.MouseDown += new MouseEventHandler(OnSurfaceMouseDown);
971      surface.MouseUp += new MouseEventHandler(OnSurfaceMouseUp);
972      surface.MouseMove += new MouseEventHandler(OnSurfaceMouseMove);
973      surface.MouseHover += new EventHandler(OnSurfaceMouseHover);
974      surface.MouseWheel += new MouseEventHandler(surface_MouseWheel);
975      #endregion
976
977      #region Keyboard events
978      surface.KeyDown += new KeyEventHandler(surface_KeyDown);
979      surface.KeyUp += new KeyEventHandler(surface_KeyUp);
980      surface.KeyPress += new KeyPressEventHandler(surface_KeyPress);
981      #endregion
982
983      #region Dragdrop events
984      surface.DragDrop += new DragEventHandler(surface_DragDrop);
985      surface.DragEnter += new DragEventHandler(surface_DragEnter);
986      surface.DragLeave += new EventHandler(surface_DragLeave);
987      surface.DragOver += new DragEventHandler(surface_DragOver);
988      surface.GiveFeedback +=
989          new GiveFeedbackEventHandler(surface_GiveFeedback);
990      #endregion
991    }
992
993    // ------------------------------------------------------------------
994    /// <summary>
995    /// Handles the MouseWheel event of the surface control.
996    /// <remarks>In the WinForm implementation this routine is not called
997    /// because it gives some flickering effects; the hotkeys are
998    /// implemented in the overriden OnMouseWheel method instead.</remarks>
999    /// </summary>
1000    /// <param name="sender">The source of the event.</param>
1001    /// <param name="e">The
1002    /// <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance
1003    /// containing the event data.</param>
1004    // ------------------------------------------------------------------
1005    void surface_MouseWheel(object sender, MouseEventArgs e) {
1006      Point p = View.Origin;
1007      SizeF magnification = View.Magnification;
1008      int newValue = 0;
1009
1010      if ((Control.ModifierKeys & Keys.Control) == Keys.Control) {
1011        #region Zooming
1012
1013        SizeF s = magnification;
1014
1015        // If zooming in, e.Delta is < 0 so a value of 1.1 is used to
1016        // offset the current magnification by.  One mouse wheel
1017        // position on my PC corresponds to a delta of 120 (positive
1018        // for zooming out, neg for zooming in).
1019        float alpha = e.Delta > 0 ? 1.1F : 0.9F;
1020        View.Magnification = new SizeF(
1021            s.Width * alpha,
1022            s.Height * alpha);
1023
1024        float w = (float)parentControl.AutoScrollPosition.X /
1025            (float)parentControl.AutoScrollMinSize.Width;
1026
1027        float h = (float)parentControl.AutoScrollPosition.Y /
1028            (float)parentControl.AutoScrollMinSize.Height;
1029
1030        // Resize the scrollbars proportionally to keep the actual
1031        // canvas constant.
1032        //s = new SizeF(
1033        //    parentControl.AutoScrollMinSize.Width * alpha,
1034        //    parentControl.AutoScrollMinSize.Height * alpha);
1035
1036        //parentControl.AutoScrollMinSize = Size.Round(s);
1037        RectangleF pageBounds = Model.CurrentPage.Bounds;
1038        pageBounds.Inflate(s);
1039        SizeF deltaSize = new SizeF(
1040            pageBounds.Width - parentControl.ClientRectangle.Width,
1041            pageBounds.Height - parentControl.ClientRectangle.Height);
1042
1043        if ((deltaSize.Width > 0) && (deltaSize.Height > 0)) {
1044          parentControl.AutoScrollMinSize = Size.Round(deltaSize);
1045        }
1046
1047        //Point v = Origin;
1048        //v.Offset(
1049        //    Convert.ToInt32((alpha - 1) * v.X),
1050        //    Convert.ToInt32((alpha - 1) * v.Y));
1051        //v.X = (int)Math.Round((double)(v.X - alpha));
1052        //v.Y = (int)Math.Round((double)(v.Y - alpha));
1053        //Origin = v;
1054
1055        #endregion
1056      } else if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) {
1057        #region Pan horizontal
1058        newValue = p.X - Math.Sign(e.Delta) * 20;
1059        if (newValue > 0)
1060          View.Origin = new Point(newValue, p.Y);
1061        else
1062          View.Origin = new Point(0, p.Y);
1063
1064        #endregion
1065      } else {
1066        #region Default vertical scroll
1067        newValue = View.Origin.Y -
1068            Math.Sign(e.Delta) * 20;
1069
1070        if (newValue > 0)
1071          View.Origin = new Point(
1072              View.Origin.X,
1073              newValue);
1074        else
1075          View.Origin = new Point(
1076              View.Origin.X,
1077              0);
1078        #endregion
1079      }
1080
1081      this.parentControl.AutoScrollPosition = View.Origin;
1082      HandledMouseEventArgs eventargs = e as HandledMouseEventArgs;
1083      if (eventargs != null)
1084        eventargs.Handled = true;
1085      View.Invalidate();
1086    }
1087
1088    #region DragDrop event handlers
1089
1090    /// <summary>
1091    /// Handles the GiveFeedback event of the surface control.
1092    /// </summary>
1093    /// <param name="sender">The source of the event.</param>
1094    /// <param name="e">The <see cref="T:System.Windows.Forms.GiveFeedbackEventArgs"/> instance containing the event data.</param>
1095    void surface_GiveFeedback(object sender, GiveFeedbackEventArgs e) {
1096      if (!controllerEnabled) {
1097        return;
1098      }
1099
1100      foreach (IDragDropListener listener in dragdropListeners) {
1101        listener.GiveFeedback(e);
1102      }
1103    }
1104    /// <summary>
1105    /// Handles the DragOver event of the surface control.
1106    /// </summary>
1107    /// <param name="sender">The source of the event.</param>
1108    /// <param name="e">The <see cref="T:System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
1109    void surface_DragOver(object sender, DragEventArgs e) {
1110      if (!controllerEnabled) {
1111        return;
1112      }
1113
1114      foreach (IDragDropListener listener in dragdropListeners) {
1115        listener.OnDragOver(e);
1116      }
1117    }
1118
1119    /// <summary>
1120    /// Handles the DragLeave event of the surface control.
1121    /// </summary>
1122    /// <param name="sender">The source of the event.</param>
1123    /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
1124    void surface_DragLeave(object sender, EventArgs e) {
1125      if (!controllerEnabled) {
1126        return;
1127      }
1128
1129      foreach (IDragDropListener listener in dragdropListeners) {
1130        listener.OnDragLeave(e);
1131      }
1132    }
1133
1134    /// <summary>
1135    /// Handles the DragEnter event of the surface control.
1136    /// </summary>
1137    /// <param name="sender">The source of the event.</param>
1138    /// <param name="e">The <see cref="T:System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
1139    void surface_DragEnter(object sender, DragEventArgs e) {
1140      if (!controllerEnabled) {
1141        return;
1142      }
1143
1144      foreach (IDragDropListener listener in dragdropListeners) {
1145        listener.OnDragEnter(e);
1146      }
1147    }
1148
1149    /// <summary>
1150    /// Handles the DragDrop event of the surface control.
1151    /// </summary>
1152    /// <param name="sender">The source of the event.</param>
1153    /// <param name="e">The <see cref="T:System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
1154    void surface_DragDrop(object sender, DragEventArgs e) {
1155      if (!controllerEnabled) {
1156        return;
1157      }
1158
1159      foreach (IDragDropListener listener in dragdropListeners) {
1160        listener.OnDragDrop(e);
1161      }
1162    }
1163    #endregion
1164
1165    #region Keyboard event handlers
1166    void surface_KeyPress(object sender, KeyPressEventArgs e) {
1167
1168      foreach (IKeyboardListener listener in keyboardListeners) {
1169        listener.KeyPress(e);
1170      }
1171
1172      foreach (IDiagramEntity entity in this.Model.Selection.SelectedItems) {
1173        if (entity is IKeyboardListener) {
1174          (entity as IKeyboardListener).KeyPress(e);
1175        }
1176      }
1177    }
1178
1179    void surface_KeyUp(object sender, KeyEventArgs e) {
1180
1181      foreach (IKeyboardListener listener in keyboardListeners) {
1182        listener.KeyUp(e);
1183      }
1184
1185      foreach (IDiagramEntity entity in this.Model.Selection.SelectedItems) {
1186        if (entity is IKeyboardListener) {
1187          (entity as IKeyboardListener).KeyUp(e);
1188        }
1189      }
1190    }
1191
1192    void surface_KeyDown(object sender, KeyEventArgs e) {
1193      foreach (IKeyboardListener listener in keyboardListeners) {
1194        listener.KeyDown(e);
1195      }
1196
1197      foreach (IDiagramEntity entity in this.Model.Selection.SelectedItems) {
1198        if (entity is IKeyboardListener) {
1199          (entity as IKeyboardListener).KeyDown(e);
1200        }
1201      }
1202    }
1203
1204    #endregion
1205
1206    #region Mouse event handlers
1207    /// <summary>
1208    /// Implements the observer pattern for the mouse hover event,
1209    /// communicating the event to all listeners implementing the
1210    /// necessary interface.
1211    /// </summary>
1212    /// <param name="sender">The source of the event.</param>
1213    /// <param name="e">The <see cref="T:System.EventArgs"/> instance
1214    /// containing the event data.</param>
1215    protected virtual void OnSurfaceMouseHover(object sender, EventArgs e) {
1216      //if (eventsEnabled)
1217      //    RaiseOnMouseHover(e);
1218      //if (!controllerEnabled)
1219      //    return; 
1220    }
1221    /// <summary>
1222    /// Implements the observer pattern for the mouse down event,
1223    /// communicating the event to all listeners implementing the
1224    /// necessary interface.
1225    /// </summary>
1226    /// <param name="sender">The source of the event.</param>
1227    /// <param name="e">The
1228    /// <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance
1229    /// containing the event data.</param>
1230    protected virtual void OnSurfaceMouseDown(
1231        object sender,
1232        MouseEventArgs e) {
1233      #region Coordinates logic
1234      // Get a point adjusted by the current scroll position and zoom factor           
1235      Point p = Point.Round(
1236          this.View.ViewToWorld(this.View.DeviceToView(e.Location)));
1237
1238      HandledMouseEventArgs ce =
1239          new HandledMouseEventArgs(
1240          e.Button,
1241          e.Clicks,
1242          p.X,
1243          p.Y,
1244          e.Delta);
1245      #endregion
1246
1247      if (eventsEnabled)
1248        RaiseOnMouseDown(ce);
1249      if (!controllerEnabled || ce.Handled)
1250        return;
1251      this.parentControl.Focus();
1252
1253      //(parentControl as Win.DiagramControl).toolTip.Show("Yihaaa", parentControl as Win.DiagramControl, ce.Location);
1254
1255      //this selection process will work independently of the tools because
1256      //some tools need the current selection or hit entity
1257      //On the other hand, when drawing a simple rectangle for example the selection
1258      //should be off, so there is an overhead.
1259      //Selection.CollectEntitiesAt(e.Location);
1260
1261      //raise the event to give the host the opportunity to show the properties of the selected item(s)
1262      //Note that if the selection is empty the property grid will show 'nothing'.
1263      RaiseOnShowSelectionProperties(new SelectionEventArgs(this.Model.Selection.SelectedItems.ToArray()));
1264
1265      foreach (IMouseListener listener in mouseListeners) {
1266        if (listener.MouseDown(ce))
1267          break;
1268      }
1269    }
1270    /// <summary>
1271    /// Handles the MouseMove event of the surface control.
1272    /// </summary>
1273    /// <param name="sender">The source of the event.</param>
1274    /// <param name="e">The
1275    /// <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance
1276    /// containing the event data.</param>
1277    protected virtual void OnSurfaceMouseMove(object sender, MouseEventArgs e) {
1278      if (!controllerEnabled)
1279        return;
1280
1281      #region Coordinates logic
1282      // Get a point adjusted by the current scroll position and zoom
1283      // factor.
1284      //Point p = new Point(e.X - parentControl.AutoScrollPosition.X, e.Y - parentControl.AutoScrollPosition.Y);
1285      Point p = Point.Round(this.View.ViewToWorld(
1286          this.View.DeviceToView(e.Location)));
1287
1288      MouseEventArgs ce = new MouseEventArgs(
1289          e.Button,
1290          e.Clicks,
1291          p.X,
1292          p.Y,
1293          e.Delta);
1294
1295      #endregion
1296      foreach (IMouseListener listener in mouseListeners) {
1297        listener.MouseMove(ce);
1298      }
1299    }
1300
1301    /// <summary>
1302    /// Handles the MouseUp event of the surface control.
1303    /// </summary>
1304    /// <param name="sender">The source of the event.</param>
1305    /// <param name="e">The <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
1306    protected virtual void OnSurfaceMouseUp(object sender, System.Windows.Forms.MouseEventArgs e) {
1307      if (!controllerEnabled)
1308        return;
1309      #region Coordinates logic
1310      // Get a point adjusted by the current scroll position and zoom factor
1311      //Point p = new Point(e.X - parentControl.AutoScrollPosition.X, e.Y - parentControl.AutoScrollPosition.Y);
1312      Point p = Point.Round(this.View.ViewToWorld(this.View.DeviceToView(e.Location)));
1313      MouseEventArgs ce = new MouseEventArgs(e.Button, e.Clicks, p.X, p.Y, e.Delta);
1314      #endregion
1315      foreach (IMouseListener listener in mouseListeners) {
1316        listener.MouseUp(ce);
1317      }
1318    }
1319
1320
1321    #endregion
1322
1323    // ------------------------------------------------------------------
1324    /// <summary>
1325    /// Undo of the last action
1326    /// </summary>
1327    /// <remarks>Calling this on a class level will call the Undo method
1328    /// of the last ICommand in the stack.</remarks>
1329    // ------------------------------------------------------------------
1330    public void Undo() {
1331      // Reset the tracker or show the tracker after the undo operation
1332      // since the undo does not take care of it
1333      this.View.ResetTracker();
1334      mUndoManager.Undo();
1335      this.View.ShowTracker();
1336      this.View.Invalidate();
1337    }
1338
1339    // ------------------------------------------------------------------
1340    /// <summary>
1341    /// Performs the actual action or redo in case the actions was undone
1342    /// before.
1343    /// </summary>
1344    /// <remarks>Calling this on a class level will call the Redo method
1345    /// of the last ICommand in the stack.</remarks>
1346    // ------------------------------------------------------------------
1347    public void Redo() {
1348      mUndoManager.Redo();
1349      this.View.ShowTracker();
1350    }
1351
1352    // ------------------------------------------------------------------
1353    /// <summary>
1354    /// Selects all entities on the current page.  The selection is
1355    /// cleared first.
1356    /// </summary>
1357    // ------------------------------------------------------------------
1358    public void SelectAll() {
1359      this.View.ResetTracker();
1360      this.Model.Selection.Clear();
1361      this.Model.Selection.SelectedItems = this.Model.CurrentPage.Entities;
1362      this.View.ShowTracker();
1363      this.View.Invalidate();
1364    }
1365
1366    // ------------------------------------------------------------------
1367    /// <summary>
1368    /// Navigates to the next page.  Nothing is performed if the last page
1369    /// is currently selected and 'wrap' is false.  If 'wrap' is true,
1370    /// then the first page is selected.
1371    /// </summary>
1372    /// <param name="wrap">bool: Specifies if the collection is wrapped
1373    /// when the end is reached.</param>
1374    // ------------------------------------------------------------------
1375    public void GoForward(bool wrap) {
1376      // We can't go anywhere if there's only one page!
1377      if (Model.Pages.Count == 1) {
1378        return;
1379      }
1380
1381      int index = Model.Pages.IndexOf(Model.CurrentPage);
1382
1383      int newIndex = 0;  // The index of the page to select.
1384
1385      if (index >= (Model.Pages.Count - 1)) {
1386        // The last page is currently active, so if 'wrap' is
1387        // false then just return.
1388        if (wrap == false) {
1389          return;
1390        }
1391
1392        // Otherwise, if 'wrap' is true then we want the first page
1393        // in the collection to be active.
1394        newIndex = 0;
1395      } else {
1396        newIndex = index + 1;
1397      }
1398
1399      DeactivateAllTools();
1400      View.HideTracker();  // Just in case there are selected items.
1401      Model.SetCurrentPage(Model.Pages[newIndex]);
1402      View.Invalidate();
1403    }
1404
1405    // ------------------------------------------------------------------
1406    /// <summary>
1407    /// Navigates to the previous page.  Nothing is performed if the first
1408    /// page is currently selected and 'wrap' is false.  If 'wrap' is
1409    /// true, then the last page is selected if the current page is the
1410    /// first page.
1411    /// </summary>
1412    /// <param name="wrap">bool: Specifies if the collection is wrapped
1413    /// when the start is reached.</param>
1414    // ------------------------------------------------------------------
1415    public void GoBack(bool wrap) {
1416      // We can't go anywhere if there's only one page!
1417      if (Model.Pages.Count == 1) {
1418        return;
1419      }
1420
1421      int index = Model.Pages.IndexOf(Model.CurrentPage);
1422
1423      int newIndex = 0;  // The index of the page to select.
1424
1425      if (index == 0) {
1426        // The first page is currently active, so if 'wrap' is
1427        // false then just return.
1428        if (wrap == false) {
1429          return;
1430        }
1431
1432        // Otherwise, since 'wrap' is true then we want the last page
1433        // in the collection to be active.
1434        newIndex = Model.Pages.Count - 1;
1435      } else {
1436        newIndex = index - 1;
1437      }
1438
1439      DeactivateAllTools();
1440      View.HideTracker();  // Just in case there are selected items.
1441      Model.SetCurrentPage(Model.Pages[newIndex]);
1442      View.Invalidate();
1443    }
1444    #endregion
1445
1446  }
1447}
Note: See TracBrowser for help on using the repository browser.