source: trunk/CrypPlugins/WorkspaceManager/WorkspaceManager.cs @ 2178

Last change on this file since 2178 was 2178, checked in by Sven Rech, 11 years ago

reworked ribbon bar

File size: 27.0 KB
Line 
1/*                             
2   Copyright 2010 Nils Kopal, Viktor M.
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15*/
16
17
18using System;
19using System.Collections.Generic;
20using System.Linq;
21using System.Text;
22using Cryptool.Core;
23using Cryptool.PluginBase.Editor;
24using Cryptool.UiPluginBase;
25using Cryptool.PluginBase.IO;
26using Cryptool.PluginBase;
27
28using WorkspaceManager.Model;
29using WorkspaceManager.View;
30using WorkspaceManager.Execution;
31using WorkspaceManager.View.Container;
32using WorkspaceManager.View.Converter;
33using System.Windows;
34using System.Windows.Threading;
35using System.Threading;
36using System.Windows.Controls;
37using System.Windows.Media;
38using Cryptool.PluginBase.Miscellaneous;
39using WorkspaceManager.View.VisualComponents;
40using System.Windows.Media.Imaging;
41using System.Printing;
42using System.Windows.Documents;
43using System.Windows.Markup;
44
45//Disable warnings for unused or unassigned fields and events:
46#pragma warning disable 0169, 0414, 0067
47
48namespace WorkspaceManager
49{
50    /// <summary>
51    /// Workspace Manager - PluginEditor based on MVC Pattern
52    /// </summary>
53    [EditorInfo("cwm")]
54    [Author("Viktor Matkovic,Nils Kopal", "nils.kopal@cryptool.org", "Universität Duisburg-Essen", "http://www.uni-due.de")]
55    [PluginInfo("WorkspaceManager.Resources.Attributes", false, "Workspace Manager", "Graphical plugin editor for the CrypTool workspace", null,
56      "AnotherEditor/icon.png",
57      "AnotherEditor/Images/addWorkspace.png",
58      "AnotherEditor/Images/deleteWorkspace.png",
59      "AnotherEditor/Images/importSubWorkspace.png")]
60    public class WorkspaceManager : IEditor
61    {
62
63        /// <summary>
64        /// Create a new Instance of the Editor
65        /// </summary>
66        public WorkspaceManager()
67        {
68            Settings = new WorkspaceManagerSettings(this);
69            WorkspaceModel = new WorkspaceModel();
70            WorkspaceModel.WorkspaceManagerEditor = this;
71            WorkspaceSpaceEditorView = new WorkSpaceEditorView(WorkspaceModel);
72            HasChanges = false;                               
73        }
74
75        #region private Members
76
77        private WorkspaceModel WorkspaceModel = null;
78        private WorkSpaceEditorView WorkspaceSpaceEditorView = null;
79        private ExecutionEngine ExecutionEngine = null;
80        private volatile bool executing = false;
81        private volatile bool stopping = false;
82
83        #endregion
84
85        /// <summary>
86        /// Is this Editor executing?
87        /// </summary>
88        public bool isExecuting(){
89            return executing;
90        }
91
92        #region IEditor Members
93
94        /// <summary>
95        ///
96        /// </summary>
97        public event ChangeDisplayLevelHandler OnChangeDisplayLevel;
98
99        /// <summary>
100        ///
101        /// </summary>
102        public event SelectedPluginChangedHandler OnSelectedPluginChanged;
103
104        /// <summary>
105        ///
106        /// </summary>
107        public event ProjectTitleChangedHandler OnProjectTitleChanged;
108
109        /// <summary>
110        ///
111        /// </summary>
112        public event OpenProjectFileHandler OnOpenProjectFile;
113
114        /// <summary>
115        ///
116        /// </summary>
117        public event EditorSpecificPluginsChanged OnEditorSpecificPluginsChanged;
118
119        /// <summary>
120        /// Current filename
121        /// </summary>
122        public string CurrentFilename { private set; get; }
123
124        /// <summary>
125        /// Called by clicking on the new button of CrypTool
126        /// Creates a new Model
127        /// </summary>
128        public void New()
129        {
130            foreach (PluginModel pluginModel in new List<PluginModel>(WorkspaceModel.AllPluginModels))
131            {
132                WorkspaceModel.deletePluginModel(pluginModel);
133            }
134            this.HasChanges = false;
135            CurrentFilename = "unnamed project";
136            this.OnProjectTitleChanged.BeginInvoke(this, "unnamed project", null, null);
137        }
138
139        /// <summary>
140        /// Called by clicking on the open button of CrypTool
141        /// loads a serialized model
142        /// </summary>
143        /// <param name="fileName"></param>
144        public void Open(string fileName)
145        {
146            try
147            {
148                New();
149                GuiLogMessage("Loading Model: " + fileName, NotificationLevel.Info);               
150                WorkspaceModel = ModelPersistance.loadModel(fileName,this);               
151                WorkspaceSpaceEditorView.Load(WorkspaceModel);
152                HasChanges = false;
153                this.OnProjectTitleChanged.BeginInvoke(this, System.IO.Path.GetFileName(fileName), null, null);
154                CurrentFilename = fileName;
155            }
156            catch (Exception ex)
157            {
158                GuiLogMessage("Could not load Model:" + ex.ToString(), NotificationLevel.Error);
159            }
160        }
161
162        /// <summary>
163        /// Called by clicking on the save button of CrypTool
164        /// serializes the current model
165        /// </summary>
166        /// <param name="fileName"></param>
167        public void Save(string fileName)
168        {
169            try
170            {
171                GuiLogMessage("Saving Model: " + fileName, NotificationLevel.Info);
172                ModelPersistance.saveModel(this.WorkspaceModel, fileName);
173                HasChanges = false;
174                this.OnProjectTitleChanged.BeginInvoke(this, System.IO.Path.GetFileName(fileName), null, null);
175                CurrentFilename = fileName;
176            }
177            catch (Exception ex)
178            {
179                GuiLogMessage("Could not save Model:" + ex.ToString(), NotificationLevel.Error);               
180            }
181           
182        }
183
184        /// <summary>
185        /// Called by double clicking on a plugin symbol of CrypTool
186        /// Adds a new PluginModel wrapping an instance of the selected plugin
187        /// </summary>
188        /// <param name="type"></param>
189        public void Add(Type type)
190        {
191            /*if (!executing)
192            {
193                PluginModel newPluginModel = WorkspaceModel.newPluginModel(new Point(10, 10), 100, 100, type);
194                GuiLogMessage("Added by double click: " + newPluginModel.Name, NotificationLevel.Info);
195                HasChanges = true;
196            }*/
197        }
198
199        /// <summary>
200        ///
201        /// </summary>
202        /// <param name="espi"></param>
203        public void AddEditorSpecific(EditorSpecificPluginInfo espi)
204        {
205            //to be implemented
206        }
207
208        /// <summary>
209        ///
210        /// </summary>
211        /// <param name="espi"></param>
212        public void DeleteEditorSpecific(EditorSpecificPluginInfo espi)
213        {
214            //to be implemented   
215        }
216
217        /// <summary>
218        /// Undo changes
219        /// </summary>
220        public void Undo()
221        {
222            //to be implemented
223        }
224
225        /// <summary>
226        /// Redo changes
227        /// </summary>
228        public void Redo()
229        {
230            //to be implemented
231        }
232
233        public void Cut()
234        {
235            throw new NotImplementedException();
236        }
237
238        public void Copy()
239        {
240            throw new NotImplementedException();
241        }
242
243        public void Paste()
244        {
245            throw new NotImplementedException();
246        }
247
248        public void Print()
249        {
250            try
251            {
252                Matrix m = PresentationSource.FromVisual(Application.Current.MainWindow).CompositionTarget.TransformToDevice;
253                double dx = m.M11 * 96;
254                double dy = m.M22 * 96;
255                this.GuiLogMessage("dx=" + dx + " dy=" + dy, NotificationLevel.Debug);
256                const int factor = 4;
257                ModifiedCanvas control = (ModifiedCanvas)((WorkSpaceEditorView)this.Presentation).ViewBox.Content;
258                PrintDialog dialog = new PrintDialog();
259                dialog.PageRangeSelection = PageRangeSelection.AllPages;
260                dialog.UserPageRangeEnabled = true;
261
262                Nullable<Boolean> print = dialog.ShowDialog();
263                if (print == true)
264                {
265                    this.GuiLogMessage("Printing document \"" + this.CurrentFilename + "\" now", NotificationLevel.Info);
266                   
267                    PrintCapabilities capabilities = dialog.PrintQueue.GetPrintCapabilities(dialog.PrintTicket);
268                    System.Windows.Size pageSize = new System.Windows.Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight);
269                    System.Windows.Size visibleSize = new System.Windows.Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
270
271                    FixedDocument fixedDoc = new FixedDocument();
272                    control.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
273                    control.Arrange(new Rect(new System.Windows.Point(0, 0), control.DesiredSize));
274                    System.Windows.Size size = control.DesiredSize;
275
276                    RenderTargetBitmap bmp = new RenderTargetBitmap((int)size.Width * factor, (int)size.Height * factor, dx * factor, dy * factor, PixelFormats.Pbgra32);
277                    bmp.Render(control);
278
279
280                    double xOffset = 0;
281                    double yOffset = 0;
282                    while (xOffset < size.Width)
283                    {
284                        yOffset = 0;
285                        while (yOffset < size.Height)
286                        {
287                            PageContent pageContent = new PageContent();
288                            FixedPage page = new FixedPage();
289                            ((IAddChild)pageContent).AddChild(page);
290                            fixedDoc.Pages.Add(pageContent);
291                            page.Width = pageSize.Width;
292                            page.Height = pageSize.Height;
293                            int width = (xOffset + visibleSize.Width) > size.Width ? (int)(size.Width - xOffset) : (int)visibleSize.Width;
294                            int height = (yOffset + visibleSize.Height) > size.Height ? (int)(size.Height - yOffset) : (int)visibleSize.Height;
295                            System.Windows.Controls.Image croppedImage = new System.Windows.Controls.Image();                           
296                            CroppedBitmap cb = new CroppedBitmap(bmp, new Int32Rect((int)xOffset * factor, (int)yOffset *factor, width * factor, height * factor));
297                            croppedImage.Source = cb;
298                            croppedImage.Width = width;
299                            croppedImage.Height = height;
300                            page.Children.Add(croppedImage);
301                            yOffset += visibleSize.Height;
302                        }
303                        xOffset += visibleSize.Width;
304                    }
305                    dialog.PrintDocument(fixedDoc.DocumentPaginator, "WorkspaceManager_" + this.CurrentFilename);
306                    this.GuiLogMessage("Printed \"" + fixedDoc.DocumentPaginator.PageCount + "\" pages of document \"" + this.CurrentFilename + "\"", NotificationLevel.Info);
307                }
308            }
309            catch (Exception ex)
310            {
311                this.GuiLogMessage("Exception while printing: " + ex.Message, NotificationLevel.Error);
312            }
313        }
314
315        /// <summary>
316        /// Show the Help site
317        /// </summary>
318        public void ShowHelp()
319        {
320            //to be implemented
321        }
322
323        /// <summary>
324        /// Show the Description of the selected plugin
325        /// </summary>
326        public void ShowSelectedPluginDescription()
327        {
328            //to be implemented
329        }
330
331        /// <summary>
332        /// Is Undo possible
333        /// </summary>
334        public bool CanUndo
335        {
336            get;
337            set;
338        }
339
340        /// <summary>
341        /// Is Redo possible?
342        /// </summary>
343        public bool CanRedo
344        {
345            get;
346            set;
347        }
348
349        public bool CanCut
350        {
351            get { return false; }
352        }
353
354        public bool CanCopy
355        {
356            get { return false; }
357        }
358
359        public bool CanPaste
360        {
361            get { return false; }
362        }
363
364        /// <summary>
365        /// Can the ExecutionEngine be started?
366        /// </summary>
367        public bool CanExecute
368        {
369            get{return !executing;}
370        }
371
372        /// <summary>
373        /// Can the ExecutionEngine be stopped?
374        /// </summary>
375        public bool CanStop
376        {
377            get { return executing; }
378        }
379
380        /// <summary>
381        /// Does this Editor has changes?
382        /// </summary>
383        public bool HasChanges
384        {
385            get;
386            set;
387        }
388
389        public bool CanPrint
390        {
391            get { return true; }
392        }
393
394        /// <summary>
395        /// DisplayLevel
396        /// </summary>
397        public DisplayLevel DisplayLevel
398        {
399            get;
400            set;
401           
402        }
403
404        /// <summary>
405        ///
406        /// </summary>
407        public List<EditorSpecificPluginInfo> EditorSpecificPlugins
408        {
409            get;
410            set;
411        }
412
413        public bool ReadOnly { get; set; }
414
415        #endregion
416
417        #region IPlugin Members
418
419        /// <summary>
420        ///
421        /// </summary>
422        public event StatusChangedEventHandler OnPluginStatusChanged;
423
424        /// <summary>
425        ///
426        /// </summary>
427        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
428
429        /// <summary>
430        ///
431        /// </summary>
432        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
433
434        /// <summary>
435        /// Settings of this editor
436        /// </summary>
437        public ISettings Settings
438        {
439            get;
440            set;
441        }
442
443        /// <summary>
444        /// The Presentation of this editor
445        /// </summary>
446        public System.Windows.Controls.UserControl Presentation
447        {
448            get {return WorkspaceSpaceEditorView;}
449            set { WorkspaceSpaceEditorView = (WorkSpaceEditorView)value; }
450        }
451
452        /// <summary>
453        /// The QuickWatchPresentation of this editor
454        /// </summary>
455        public System.Windows.Controls.UserControl QuickWatchPresentation
456        {
457            get;
458            set;
459        }
460
461        /// <summary>
462        /// Called before execution
463        /// </summary>
464        public void PreExecution()
465        {
466            //to be implemented
467        }
468
469        /// <summary>
470        /// Starts the ExecutionEngine to execute the model
471        /// </summary>
472        public void Execute()
473        {
474            if (executing)
475            {
476                return;
477            }
478            EventsHelper.AsynchronousPropertyChanged = false;
479            try
480            {
481                GuiLogMessage("Execute Model now!", NotificationLevel.Info);
482                executing = true;
483
484                if (((WorkspaceManagerSettings)this.Settings).SynchronousEvents)
485                {
486                    EventsHelper.AsynchronousProgressChanged = false;
487                    EventsHelper.AsynchronousGuiLogMessage = false;
488                    EventsHelper.AsynchronousStatusChanged = false;
489                }
490
491                //Get the gui Thread
492                this.WorkspaceSpaceEditorView.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
493                {
494                    this.WorkspaceSpaceEditorView.ResetConnections();
495                    this.WorkspaceSpaceEditorView.State = EditorState.BUSY;                   
496                }
497                , null);
498
499                this.ExecutionEngine = new ExecutionEngine(this);
500
501                try
502                {
503                    ExecutionEngine.GuiUpdateInterval = int.Parse(((WorkspaceManagerSettings)this.Settings).GuiUpdateInterval);
504                    if (ExecutionEngine.GuiUpdateInterval <= 0)
505                    {
506                        GuiLogMessage("GuiUpdateInterval can not be <=0; Use GuiUpdateInterval = 1", NotificationLevel.Warning);
507                        ExecutionEngine.GuiUpdateInterval = 1;
508                    }
509                }
510                catch (Exception ex)
511                {
512                    GuiLogMessage("Could not set GuiUpdateInterval: " + ex.Message, NotificationLevel.Warning);
513                    ExecutionEngine.GuiUpdateInterval = 100;
514                }
515
516                try
517                {
518                    ExecutionEngine.SleepTime = int.Parse(((WorkspaceManagerSettings)this.Settings).SleepTime);
519                    if (ExecutionEngine.SleepTime < 0)
520                    {
521                        GuiLogMessage("SleepTime can not be <=0; Use GuiUpdateInterval = 0", NotificationLevel.Warning);
522                        ExecutionEngine.SleepTime = 0;
523                    }
524                }
525                catch (Exception ex)
526                {
527                    GuiLogMessage("Could not set SleepTime: " + ex.Message, NotificationLevel.Warning);
528                    ExecutionEngine.GuiUpdateInterval = 0;
529                }
530
531                int schedulers=0;
532                try
533                {
534                   schedulers = int.Parse(((WorkspaceManagerSettings)this.Settings).Threads);
535                    if (ExecutionEngine.SleepTime < 0)
536                    {
537                        GuiLogMessage("Schedulers can not be <=0; Use Schedulers = 1", NotificationLevel.Warning);
538                        schedulers = 1;
539                    }
540                }
541                catch (Exception ex)
542                {
543                    GuiLogMessage("Could not set Schedulers: " + ex.Message, NotificationLevel.Warning);
544                    schedulers = 1;
545                }
546
547                ExecutionEngine.BenchmarkPlugins = ((WorkspaceManagerSettings)this.Settings).BenchmarkPlugins;
548                ExecutionEngine.ThreadPriority = ((WorkspaceManagerSettings)this.Settings).ThreadPriority;
549
550                ExecutionEngine.Execute(WorkspaceModel, schedulers);               
551            }
552            catch (Exception ex)
553            {
554                GuiLogMessage("Exception during the execution: " + ex.Message, NotificationLevel.Error);
555                executing = false;
556                if (((WorkspaceManagerSettings)this.Settings).SynchronousEvents)
557                {
558                    EventsHelper.AsynchronousProgressChanged = true;
559                    EventsHelper.AsynchronousGuiLogMessage = true;
560                    EventsHelper.AsynchronousStatusChanged = true;
561                }
562            }
563        }
564
565        /// <summary>
566        /// Called after the execution
567        /// </summary>
568        public void PostExecution()
569        {
570            //to be implemented
571        }
572
573        /// <summary>
574        /// Pause the execution
575        /// </summary>
576        public void Pause()
577        {   
578            //to be implemented
579        }
580
581        /// <summary>
582        /// Stop the ExecutionEngine
583        /// </summary>
584        public void Stop()
585        {
586            if (!executing || stopping)
587            {
588                return;
589            }
590
591            stopping = true;
592
593            Thread stopThread = new Thread(new ThreadStart(waitingStop));
594            stopThread.Start(); 
595
596            EventsHelper.AsynchronousPropertyChanged = true;
597
598            if (((WorkspaceManagerSettings)this.Settings).SynchronousEvents)
599            {
600                EventsHelper.AsynchronousProgressChanged = true;
601                EventsHelper.AsynchronousGuiLogMessage = true;
602                EventsHelper.AsynchronousStatusChanged = true;
603            }
604
605                       
606        }
607
608        /// <summary>
609        /// Stops the execution engine and blocks until this work is done
610        /// </summary>
611        private void waitingStop()
612        {
613            try
614            {
615                GuiLogMessage("Executing stopped by User!", NotificationLevel.Info);
616                ExecutionEngine.Stop();
617                //Get the gui Thread
618                this.WorkspaceSpaceEditorView.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
619                {
620                    this.WorkspaceSpaceEditorView.ResetConnections();
621                    this.WorkspaceSpaceEditorView.State = EditorState.READY;
622                }
623                , null);
624            }
625            catch (Exception ex)
626            {
627                GuiLogMessage("Exception during the stopping of the execution: " + ex.Message, NotificationLevel.Error);
628            }
629            executing = false;
630            this.ExecutionEngine = null;
631            GC.Collect();
632            stopping = false;
633        }
634
635        /// <summary>
636        /// Called to initialize the editor
637        /// </summary>
638        public void Initialize()
639        {
640            //to be implemented
641        }
642
643        /// <summary>
644        /// Called when the editor is disposed
645        /// </summary>
646        public void Dispose()
647        {
648            if (ExecutionEngine != null && ExecutionEngine.IsRunning)
649            {
650                ExecutionEngine.Stop();
651            }
652            EventsHelper.AsynchronousPropertyChanged = true;
653        }
654
655        #endregion
656
657        #region INotifyPropertyChanged Members
658
659        /// <summary>
660        ///
661        /// </summary>
662        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
663
664        #endregion
665
666        #region IApplication Members
667
668        /// <summary>
669        ///
670        /// </summary>
671        private PluginManager pluginManager;
672        public PluginManager PluginManager
673        {
674            get { return pluginManager; }
675            set
676            {
677                pluginManager = value;
678                DragDropDataObjectToPluginConverter.PluginManager = value;
679            }         
680        }
681
682        #endregion
683
684        #region GuiLogMessage, Progress
685
686        /// <summary>
687        /// Loggs a message to the logging mechanism of CrypTool
688        /// </summary>
689        /// <param name="Message"></param>
690        /// <param name="notificationLevel"></param>
691        public void GuiLogMessage(string Message, NotificationLevel notificationLevel)
692        {
693            if (OnGuiLogNotificationOccured != null)
694            {
695                GuiLogEventArgs args = new GuiLogEventArgs(Message, this, notificationLevel);
696                args.Title = "-";
697                OnGuiLogNotificationOccured(this, args);
698            }
699        }
700
701        /// <summary>
702        /// GuiLogNotificationOccured
703        /// </summary>
704        /// <param name="sender"></param>
705        /// <param name="args"></param>
706        public void GuiLogNotificationOccured(IPlugin sender, GuiLogEventArgs args)
707        {
708            //Check if the logging event is Warning or Error and set the State of the PluginModel to
709            //the corresponding PluginModelState
710            if (args.NotificationLevel == NotificationLevel.Warning)
711            {               
712                foreach (PluginModel pluginModel in this.WorkspaceModel.AllPluginModels)
713                {
714                    if (pluginModel.Plugin == sender)
715                    {
716                        pluginModel.State = PluginModelState.Warning;
717                        pluginModel.GuiNeedsUpdate = true;
718                    }
719                }
720            }
721
722            if (args.NotificationLevel == NotificationLevel.Error)
723            {               
724                foreach (PluginModel pluginModel in this.WorkspaceModel.AllPluginModels)
725                {
726                    if (pluginModel.Plugin == sender)
727                    {
728                        pluginModel.State = PluginModelState.Error;
729                        pluginModel.GuiNeedsUpdate = true;
730                    }
731                }
732            }
733
734            if (OnGuiLogNotificationOccured != null)
735            {
736                switch (((WorkspaceManagerSettings)this.Settings).LogLevel)
737                {
738                    case 3://Error
739                        if (args.NotificationLevel == NotificationLevel.Debug ||
740                            args.NotificationLevel == NotificationLevel.Info ||
741                            args.NotificationLevel == NotificationLevel.Warning)
742                        {
743                            return;
744                        }
745                        break;
746
747                    case 2://Warning
748                        if (args.NotificationLevel == NotificationLevel.Debug ||
749                            args.NotificationLevel == NotificationLevel.Info)
750                        {
751                            return;
752                        }
753                        break;
754
755                    case 1://Info
756                        if (args.NotificationLevel == NotificationLevel.Debug)
757                        {
758                            return;
759                        }
760                        break;
761                }
762                OnGuiLogNotificationOccured(sender, args);
763            }
764               
765        }
766
767        /// <summary>
768        /// Progress of this editor
769        /// </summary>
770        /// <param name="Value"></param>
771        /// <param name="MaxValue"></param>
772        private void Progress(int Value, int MaxValue)
773        {
774            if (OnPluginProgressChanged != null)
775            {
776                OnPluginProgressChanged(this, new PluginProgressEventArgs(Value, MaxValue));
777            }
778        }
779        #endregion GuiLogMessage, Progress
780
781        /// <summary>
782        /// Selected Plugin changed by View
783        /// </summary>
784        /// <param name="args"></param>
785        public void onSelectedPluginChanged(PluginChangedEventArgs args)
786        {
787            this.OnSelectedPluginChanged(this, args);
788        }
789
790        #region IEditor Members
791
792
793        public void Active()
794        {           
795        }
796
797        #endregion
798
799        #region IEditor Members
800
801
802        public event OpenTabHandler OnOpenTab;
803
804        #endregion
805    }
806}
807
808//Restore warnings for unused or unassigned fields and events:
809#pragma warning restore 0169, 0414, 0067
Note: See TracBrowser for help on using the repository browser.