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

Last change on this file since 2167 was 2167, checked in by kopal, 11 years ago
File size: 22.2 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;
39
40//Disable warnings for unused or unassigned fields and events:
41#pragma warning disable 0169, 0414, 0067
42
43namespace WorkspaceManager
44{
45    /// <summary>
46    /// Workspace Manager - PluginEditor based on MVC Pattern
47    /// </summary>
48    [EditorInfo("cwm")]
49    [Author("Viktor Matkovic,Nils Kopal", "nils.kopal@cryptool.org", "Universität Duisburg-Essen", "http://www.uni-due.de")]
50    [PluginInfo("WorkspaceManager.Resources.Attributes", false, "Workspace Manager", "Graphical plugin editor for the CrypTool workspace", null,
51      "AnotherEditor/icon.png",
52      "AnotherEditor/Images/addWorkspace.png",
53      "AnotherEditor/Images/deleteWorkspace.png",
54      "AnotherEditor/Images/importSubWorkspace.png")]
55    public class WorkspaceManager : IEditor
56    {
57
58        /// <summary>
59        /// Create a new Instance of the Editor
60        /// </summary>
61        public WorkspaceManager()
62        {
63            Settings = new WorkspaceManagerSettings(this);
64            WorkspaceModel = new WorkspaceModel();
65            WorkspaceModel.WorkspaceManagerEditor = this;
66            WorkspaceSpaceEditorView = new WorkSpaceEditorView(WorkspaceModel);
67            HasChanges = false;                               
68        }
69
70        #region private Members
71
72        private WorkspaceModel WorkspaceModel = null;
73        private WorkSpaceEditorView WorkspaceSpaceEditorView = null;
74        private ExecutionEngine ExecutionEngine = null;
75        private volatile bool executing = false;
76        private volatile bool stopping = false;
77
78        #endregion
79
80        /// <summary>
81        /// Is this Editor executing?
82        /// </summary>
83        public bool isExecuting(){
84            return executing;
85        }
86
87        #region IEditor Members
88
89        /// <summary>
90        ///
91        /// </summary>
92        public event ChangeDisplayLevelHandler OnChangeDisplayLevel;
93
94        /// <summary>
95        ///
96        /// </summary>
97        public event SelectedPluginChangedHandler OnSelectedPluginChanged;
98
99        /// <summary>
100        ///
101        /// </summary>
102        public event ProjectTitleChangedHandler OnProjectTitleChanged;
103
104        /// <summary>
105        ///
106        /// </summary>
107        public event OpenProjectFileHandler OnOpenProjectFile;
108
109        /// <summary>
110        ///
111        /// </summary>
112        public event EditorSpecificPluginsChanged OnEditorSpecificPluginsChanged;
113
114        /// <summary>
115        /// Current filename
116        /// </summary>
117        public string CurrentFilename { private set; get; }
118
119        /// <summary>
120        /// Called by clicking on the new button of CrypTool
121        /// Creates a new Model
122        /// </summary>
123        public void New()
124        {
125            foreach (PluginModel pluginModel in new List<PluginModel>(WorkspaceModel.AllPluginModels))
126            {
127                WorkspaceModel.deletePluginModel(pluginModel);
128            }
129            this.HasChanges = false;
130            CurrentFilename = "unnamed project";
131            this.OnProjectTitleChanged.BeginInvoke(this, "unnamed project", null, null);
132        }
133
134        /// <summary>
135        /// Called by clicking on the open button of CrypTool
136        /// loads a serialized model
137        /// </summary>
138        /// <param name="fileName"></param>
139        public void Open(string fileName)
140        {
141            try
142            {
143                New();
144                GuiLogMessage("Loading Model: " + fileName, NotificationLevel.Info);               
145                WorkspaceModel = ModelPersistance.loadModel(fileName,this);               
146                WorkspaceSpaceEditorView.Load(WorkspaceModel);
147                HasChanges = false;
148                this.OnProjectTitleChanged.BeginInvoke(this, System.IO.Path.GetFileName(fileName), null, null);
149                CurrentFilename = fileName;
150            }
151            catch (Exception ex)
152            {
153                GuiLogMessage("Could not load Model:" + ex.ToString(), NotificationLevel.Error);
154            }
155        }
156
157        /// <summary>
158        /// Called by clicking on the save button of CrypTool
159        /// serializes the current model
160        /// </summary>
161        /// <param name="fileName"></param>
162        public void Save(string fileName)
163        {
164            try
165            {
166                GuiLogMessage("Saving Model: " + fileName, NotificationLevel.Info);
167                ModelPersistance.saveModel(this.WorkspaceModel, fileName);
168                HasChanges = false;
169                this.OnProjectTitleChanged.BeginInvoke(this, System.IO.Path.GetFileName(fileName), null, null);
170                CurrentFilename = fileName;
171            }
172            catch (Exception ex)
173            {
174                GuiLogMessage("Could not save Model:" + ex.ToString(), NotificationLevel.Error);               
175            }
176           
177        }
178
179        /// <summary>
180        /// Called by double clicking on a plugin symbol of CrypTool
181        /// Adds a new PluginModel wrapping an instance of the selected plugin
182        /// </summary>
183        /// <param name="type"></param>
184        public void Add(Type type)
185        {
186            /*if (!executing)
187            {
188                PluginModel newPluginModel = WorkspaceModel.newPluginModel(new Point(10, 10), 100, 100, type);
189                GuiLogMessage("Added by double click: " + newPluginModel.Name, NotificationLevel.Info);
190                HasChanges = true;
191            }*/
192        }
193
194        /// <summary>
195        ///
196        /// </summary>
197        /// <param name="espi"></param>
198        public void AddEditorSpecific(EditorSpecificPluginInfo espi)
199        {
200            //to be implemented
201        }
202
203        /// <summary>
204        ///
205        /// </summary>
206        /// <param name="espi"></param>
207        public void DeleteEditorSpecific(EditorSpecificPluginInfo espi)
208        {
209            //to be implemented   
210        }
211
212        /// <summary>
213        /// Undo changes
214        /// </summary>
215        public void Undo()
216        {
217            //to be implemented
218        }
219
220        /// <summary>
221        /// Redo changes
222        /// </summary>
223        public void Redo()
224        {
225            //to be implemented
226        }
227
228        /// <summary>
229        /// Show the Help site
230        /// </summary>
231        public void ShowHelp()
232        {
233            //to be implemented
234        }
235
236        /// <summary>
237        /// Show the Description of the selected plugin
238        /// </summary>
239        public void ShowSelectedPluginDescription()
240        {
241            //to be implemented
242        }
243
244        /// <summary>
245        /// Is Undo possible
246        /// </summary>
247        public bool CanUndo
248        {
249            get;
250            set;
251        }
252
253        /// <summary>
254        /// Is Redo possible?
255        /// </summary>
256        public bool CanRedo
257        {
258            get;
259            set;
260        }
261
262        /// <summary>
263        /// Can the ExecutionEngine be started?
264        /// </summary>
265        public bool CanExecute
266        {
267            get{return !executing;}
268        }
269
270        /// <summary>
271        /// Can the ExecutionEngine be stopped?
272        /// </summary>
273        public bool CanStop
274        {
275            get { return executing; }
276        }
277
278        /// <summary>
279        /// Does this Editor has changes?
280        /// </summary>
281        public bool HasChanges
282        {
283            get;
284            set;
285        }
286
287        /// <summary>
288        /// DisplayLevel
289        /// </summary>
290        public DisplayLevel DisplayLevel
291        {
292            get;
293            set;
294           
295        }
296
297        /// <summary>
298        ///
299        /// </summary>
300        public List<EditorSpecificPluginInfo> EditorSpecificPlugins
301        {
302            get;
303            set;
304        }
305
306        public bool ReadOnly { get; set; }
307
308        #endregion
309
310        #region IPlugin Members
311
312        /// <summary>
313        ///
314        /// </summary>
315        public event StatusChangedEventHandler OnPluginStatusChanged;
316
317        /// <summary>
318        ///
319        /// </summary>
320        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
321
322        /// <summary>
323        ///
324        /// </summary>
325        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
326
327        /// <summary>
328        /// Settings of this editor
329        /// </summary>
330        public ISettings Settings
331        {
332            get;
333            set;
334        }
335
336        /// <summary>
337        /// The Presentation of this editor
338        /// </summary>
339        public System.Windows.Controls.UserControl Presentation
340        {
341            get {return WorkspaceSpaceEditorView;}
342            set { WorkspaceSpaceEditorView = (WorkSpaceEditorView)value; }
343        }
344
345        /// <summary>
346        /// The QuickWatchPresentation of this editor
347        /// </summary>
348        public System.Windows.Controls.UserControl QuickWatchPresentation
349        {
350            get;
351            set;
352        }
353
354        /// <summary>
355        /// Called before execution
356        /// </summary>
357        public void PreExecution()
358        {
359            //to be implemented
360        }
361
362        /// <summary>
363        /// Starts the ExecutionEngine to execute the model
364        /// </summary>
365        public void Execute()
366        {
367            if (executing)
368            {
369                return;
370            }
371            EventsHelper.AsynchronousPropertyChanged = false;
372            try
373            {
374                GuiLogMessage("Execute Model now!", NotificationLevel.Info);
375                executing = true;
376
377                if (((WorkspaceManagerSettings)this.Settings).SynchronousEvents)
378                {
379                    EventsHelper.AsynchronousProgressChanged = false;
380                    EventsHelper.AsynchronousGuiLogMessage = false;
381                    EventsHelper.AsynchronousStatusChanged = false;
382                }
383
384                //Get the gui Thread
385                this.WorkspaceSpaceEditorView.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
386                {
387                    this.WorkspaceSpaceEditorView.ResetConnections();
388                    this.WorkspaceSpaceEditorView.State = EditorState.BUSY;                   
389                }
390                , null);
391
392                this.ExecutionEngine = new ExecutionEngine(this);
393
394                try
395                {
396                    ExecutionEngine.GuiUpdateInterval = int.Parse(((WorkspaceManagerSettings)this.Settings).GuiUpdateInterval);
397                    if (ExecutionEngine.GuiUpdateInterval <= 0)
398                    {
399                        GuiLogMessage("GuiUpdateInterval can not be <=0; Use GuiUpdateInterval = 1", NotificationLevel.Warning);
400                        ExecutionEngine.GuiUpdateInterval = 1;
401                    }
402                }
403                catch (Exception ex)
404                {
405                    GuiLogMessage("Could not set GuiUpdateInterval: " + ex.Message, NotificationLevel.Warning);
406                    ExecutionEngine.GuiUpdateInterval = 100;
407                }
408
409                try
410                {
411                    ExecutionEngine.SleepTime = int.Parse(((WorkspaceManagerSettings)this.Settings).SleepTime);
412                    if (ExecutionEngine.SleepTime < 0)
413                    {
414                        GuiLogMessage("SleepTime can not be <=0; Use GuiUpdateInterval = 0", NotificationLevel.Warning);
415                        ExecutionEngine.SleepTime = 0;
416                    }
417                }
418                catch (Exception ex)
419                {
420                    GuiLogMessage("Could not set SleepTime: " + ex.Message, NotificationLevel.Warning);
421                    ExecutionEngine.GuiUpdateInterval = 0;
422                }
423
424                int schedulers=0;
425                try
426                {
427                   schedulers = int.Parse(((WorkspaceManagerSettings)this.Settings).Threads);
428                    if (ExecutionEngine.SleepTime < 0)
429                    {
430                        GuiLogMessage("Schedulers can not be <=0; Use Schedulers = 1", NotificationLevel.Warning);
431                        schedulers = 1;
432                    }
433                }
434                catch (Exception ex)
435                {
436                    GuiLogMessage("Could not set Schedulers: " + ex.Message, NotificationLevel.Warning);
437                    schedulers = 1;
438                }
439
440                ExecutionEngine.BenchmarkPlugins = ((WorkspaceManagerSettings)this.Settings).BenchmarkPlugins;
441                ExecutionEngine.ThreadPriority = ((WorkspaceManagerSettings)this.Settings).ThreadPriority;
442
443                ExecutionEngine.Execute(WorkspaceModel, schedulers);               
444            }
445            catch (Exception ex)
446            {
447                GuiLogMessage("Exception during the execution: " + ex.Message, NotificationLevel.Error);
448                executing = false;
449                if (((WorkspaceManagerSettings)this.Settings).SynchronousEvents)
450                {
451                    EventsHelper.AsynchronousProgressChanged = true;
452                    EventsHelper.AsynchronousGuiLogMessage = true;
453                    EventsHelper.AsynchronousStatusChanged = true;
454                }
455            }
456        }
457
458        /// <summary>
459        /// Called after the execution
460        /// </summary>
461        public void PostExecution()
462        {
463            //to be implemented
464        }
465
466        /// <summary>
467        /// Pause the execution
468        /// </summary>
469        public void Pause()
470        {   
471            //to be implemented
472        }
473
474        /// <summary>
475        /// Stop the ExecutionEngine
476        /// </summary>
477        public void Stop()
478        {
479            if (!executing || stopping)
480            {
481                return;
482            }
483
484            stopping = true;
485
486            Thread stopThread = new Thread(new ThreadStart(waitingStop));
487            stopThread.Start(); 
488
489            EventsHelper.AsynchronousPropertyChanged = true;
490
491            if (((WorkspaceManagerSettings)this.Settings).SynchronousEvents)
492            {
493                EventsHelper.AsynchronousProgressChanged = true;
494                EventsHelper.AsynchronousGuiLogMessage = true;
495                EventsHelper.AsynchronousStatusChanged = true;
496            }
497
498                       
499        }
500
501        /// <summary>
502        /// Stops the execution engine and blocks until this work is done
503        /// </summary>
504        private void waitingStop()
505        {
506            try
507            {
508                GuiLogMessage("Executing stopped by User!", NotificationLevel.Info);
509                ExecutionEngine.Stop();
510                //Get the gui Thread
511                this.WorkspaceSpaceEditorView.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
512                {
513                    this.WorkspaceSpaceEditorView.ResetConnections();
514                    this.WorkspaceSpaceEditorView.State = EditorState.READY;
515                }
516                , null);
517            }
518            catch (Exception ex)
519            {
520                GuiLogMessage("Exception during the stopping of the execution: " + ex.Message, NotificationLevel.Error);
521            }
522            executing = false;
523            this.ExecutionEngine = null;
524            GC.Collect();
525            stopping = false;
526        }
527
528        /// <summary>
529        /// Called to initialize the editor
530        /// </summary>
531        public void Initialize()
532        {
533            //to be implemented
534        }
535
536        /// <summary>
537        /// Called when the editor is disposed
538        /// </summary>
539        public void Dispose()
540        {
541            if (ExecutionEngine != null && ExecutionEngine.IsRunning)
542            {
543                ExecutionEngine.Stop();
544            }
545            EventsHelper.AsynchronousPropertyChanged = true;
546        }
547
548        #endregion
549
550        #region INotifyPropertyChanged Members
551
552        /// <summary>
553        ///
554        /// </summary>
555        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
556
557        #endregion
558
559        #region IApplication Members
560
561        /// <summary>
562        ///
563        /// </summary>
564        private PluginManager pluginManager;
565        public PluginManager PluginManager
566        {
567            get { return pluginManager; }
568            set
569            {
570                pluginManager = value;
571                DragDropDataObjectToPluginConverter.PluginManager = value;
572            }         
573        }
574
575        #endregion
576
577        #region GuiLogMessage, Progress
578
579        /// <summary>
580        /// Loggs a message to the logging mechanism of CrypTool
581        /// </summary>
582        /// <param name="Message"></param>
583        /// <param name="notificationLevel"></param>
584        public void GuiLogMessage(string Message, NotificationLevel notificationLevel)
585        {
586            if (OnGuiLogNotificationOccured != null)
587            {
588                GuiLogEventArgs args = new GuiLogEventArgs(Message, this, notificationLevel);
589                args.Title = "-";
590                OnGuiLogNotificationOccured(this, args);
591            }
592        }
593
594        /// <summary>
595        /// GuiLogNotificationOccured
596        /// </summary>
597        /// <param name="sender"></param>
598        /// <param name="args"></param>
599        public void GuiLogNotificationOccured(IPlugin sender, GuiLogEventArgs args)
600        {
601            //Check if the logging event is Warning or Error and set the State of the PluginModel to
602            //the corresponding PluginModelState
603            if (args.NotificationLevel == NotificationLevel.Warning)
604            {               
605                foreach (PluginModel pluginModel in this.WorkspaceModel.AllPluginModels)
606                {
607                    if (pluginModel.Plugin == sender)
608                    {
609                        pluginModel.State = PluginModelState.Warning;
610                        pluginModel.GuiNeedsUpdate = true;
611                    }
612                }
613            }
614
615            if (args.NotificationLevel == NotificationLevel.Error)
616            {               
617                foreach (PluginModel pluginModel in this.WorkspaceModel.AllPluginModels)
618                {
619                    if (pluginModel.Plugin == sender)
620                    {
621                        pluginModel.State = PluginModelState.Error;
622                        pluginModel.GuiNeedsUpdate = true;
623                    }
624                }
625            }
626
627            if (OnGuiLogNotificationOccured != null)
628            {
629                switch (((WorkspaceManagerSettings)this.Settings).LogLevel)
630                {
631                    case 3://Error
632                        if (args.NotificationLevel == NotificationLevel.Debug ||
633                            args.NotificationLevel == NotificationLevel.Info ||
634                            args.NotificationLevel == NotificationLevel.Warning)
635                        {
636                            return;
637                        }
638                        break;
639
640                    case 2://Warning
641                        if (args.NotificationLevel == NotificationLevel.Debug ||
642                            args.NotificationLevel == NotificationLevel.Info)
643                        {
644                            return;
645                        }
646                        break;
647
648                    case 1://Info
649                        if (args.NotificationLevel == NotificationLevel.Debug)
650                        {
651                            return;
652                        }
653                        break;
654                }
655                OnGuiLogNotificationOccured(sender, args);
656            }
657               
658        }
659
660        /// <summary>
661        /// Progress of this editor
662        /// </summary>
663        /// <param name="Value"></param>
664        /// <param name="MaxValue"></param>
665        private void Progress(int Value, int MaxValue)
666        {
667            if (OnPluginProgressChanged != null)
668            {
669                OnPluginProgressChanged(this, new PluginProgressEventArgs(Value, MaxValue));
670            }
671        }
672        #endregion GuiLogMessage, Progress
673
674        /// <summary>
675        /// Selected Plugin changed by View
676        /// </summary>
677        /// <param name="args"></param>
678        public void onSelectedPluginChanged(PluginChangedEventArgs args)
679        {
680            this.OnSelectedPluginChanged(this, args);
681        }
682
683        #region IEditor Members
684
685
686        public void Active()
687        {           
688        }
689
690        #endregion
691
692        #region IEditor Members
693
694
695        public event OpenTabHandler OnOpenTab;
696
697        #endregion
698    }
699}
700
701//Restore warnings for unused or unassigned fields and events:
702#pragma warning restore 0169, 0414, 0067
Note: See TracBrowser for help on using the repository browser.