source: trunk/CrypPlugins/WorkspaceManager/Model/PluginModel.cs @ 1684

Last change on this file since 1684 was 1684, checked in by kopal, 11 years ago
  • error messages or warning messages now lead to coloring of the plugins view (currently color stays then) - plugins with error messages will not be executed again in the current run of the chain
  • a plugin now will be executed if all mandatory connectors are set (regardless if other connectors have data)
  • corrected calls of plugin methods (Execute, PreExecution...) according to state diagram of https://www.cryptool.org/trac/CrypTool2/wiki/IPluginHints
  • bug fix in view: PluginContainerView now does not flash between icon and Presentation if it is resized
File size: 14.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.PluginBase;
23using System.Threading;
24using System.Windows.Controls;
25using Gears4Net;
26using WorkspaceManager.Execution;
27using System.Windows.Threading;
28using Cryptool.PluginBase.IO;
29using System.Reflection;
30
31namespace WorkspaceManager.Model
32{
33    /// <summary>
34    /// Class to represent and wrap a IPlugin in our model graph
35    /// </summary>
36    [Serializable]
37    public class PluginModel : VisualElementModel
38    {
39        #region privates
40        [NonSerialized]
41        private PluginProtocol pluginProtocol;
42        [NonSerialized]
43        private IPlugin plugin;         
44        private int imageIndex = 0;
45        private PluginModelState state = PluginModelState.Normal;
46        #endregion privates
47
48        /// <summary>
49        /// State of the Plugin
50        /// </summary>
51       
52        public PluginModelState State {
53            get { return state; } 
54            set { state = value; }
55        }
56
57        /// <summary>
58        /// All ingoing connectors of this PluginModel
59        /// </summary>
60        public List<ConnectorModel> InputConnectors = null;
61
62        /// <summary>
63        /// All outgoing connectors of this PluginModel
64        /// </summary>
65        public List<ConnectorModel> OutputConnectors = null;
66
67        /// <summary>
68        /// The wrapped IPlugin of this PluginModel
69        /// if there is currently no plugin instance it
70        /// will automatically create one. Otherwise
71        /// this acts as singleton and returns the created
72        /// instance
73        /// </summary>
74        public IPlugin Plugin{
75            get { 
76                if(plugin==null && PluginType != null){
77                    plugin = PluginType.CreateObject();                   
78                }
79                return plugin;
80            }
81
82            private set
83            {
84                plugin = value;
85            }
86        } 
87
88        /// <summary>
89        /// The Type of the Wrapped IPlugin of this PluginModel
90        /// Depending on this the Plugin of this PluginModel will be instanciated
91        /// </summary>       
92        public Type PluginType = null;
93
94        /// <summary>
95        /// Is the wrapped plugin startable
96        /// </summary>
97        public bool Startable;
98       
99        /// <summary>
100        /// Is the Plugin actually minimized?
101        /// </summary>
102        public bool Minimized { get; set; }
103
104        /// <summary>
105        /// The execution state of the progress of the wrapped plugin
106        /// </summary>
107        public double PercentageFinished { get; set; }
108
109        /// <summary>
110        /// Create a new PluginModel
111        /// </summary>
112        public PluginModel()
113        {
114            this.InputConnectors = new List<ConnectorModel>();
115            this.OutputConnectors = new List<ConnectorModel>();
116        }
117
118        /// <summary>
119        /// The WorkspaceModel of this PluginModel
120        /// </summary>
121        public WorkspaceModel WorkspaceModel { get; set; }
122
123        /// <summary>
124        /// Generates all Connectors of this Plugin.
125        /// </summary>
126        public void generateConnectors()
127        {
128
129            if (Plugin != null)
130            {   
131                foreach (PropertyInfoAttribute propertyInfoAttribute in Plugin.GetProperties())
132                {
133                    if (propertyInfoAttribute.Direction.Equals(Direction.InputData))
134                    {
135                        ConnectorModel connectorModel = new ConnectorModel();
136                        connectorModel.ConnectorType = propertyInfoAttribute.PropertyInfo.PropertyType;
137                        connectorModel.WorkspaceModel = WorkspaceModel;
138                        connectorModel.PluginModel = this;
139                        connectorModel.IsMandatory = propertyInfoAttribute.Mandatory;
140                        connectorModel.PropertyName = propertyInfoAttribute.PropertyName;
141                        connectorModel.ToolTip = propertyInfoAttribute.ToolTip;
142                        connectorModel.ConnectorOrientation = ConnectorOrientation.West;
143                        InputConnectors.Add(connectorModel);
144                        WorkspaceModel.AllConnectorModels.Add(connectorModel);
145                    }
146                    else if (propertyInfoAttribute.Direction.Equals(Direction.OutputData))
147                    {
148                        ConnectorModel connectorModel = new ConnectorModel();
149                        connectorModel.ConnectorType = propertyInfoAttribute.PropertyInfo.PropertyType;
150                        connectorModel.WorkspaceModel = WorkspaceModel;
151                        connectorModel.PluginModel = this;
152                        connectorModel.IsMandatory = propertyInfoAttribute.Mandatory;
153                        connectorModel.PropertyName = propertyInfoAttribute.PropertyName;
154                        connectorModel.ToolTip = propertyInfoAttribute.ToolTip;
155                        connectorModel.ConnectorOrientation = ConnectorOrientation.East;
156                        connectorModel.Outgoing = true;
157                        Plugin.PropertyChanged += connectorModel.PropertyChangedOnPlugin;
158                        OutputConnectors.Add(connectorModel);
159                        WorkspaceModel.AllConnectorModels.Add(connectorModel);
160                    }
161                }
162
163                Dictionary<string, DynamicProperty> dictionary = Plugin.GetDynamicPropertyList();
164                if (dictionary != null)
165                {
166                    DynamicPropertyInfoAttribute dynamicPropertyInfoAttribute = Plugin.GetDynamicPropertyInfo();
167                    foreach (DynamicProperty dynamicProperty in dictionary.Values)
168                    {
169
170                        if (dynamicProperty.PInfo.Direction.Equals(Direction.InputData))
171                        {
172                            ConnectorModel connectorModel = new ConnectorModel();
173                            connectorModel.ConnectorType = dynamicProperty.Type;
174                            connectorModel.WorkspaceModel = WorkspaceModel;
175                            connectorModel.PluginModel = this;
176                            connectorModel.IsMandatory = dynamicProperty.PInfo.Mandatory;
177                            connectorModel.PropertyName = dynamicProperty.Name;                           
178                            connectorModel.ToolTip = dynamicProperty.PInfo.ToolTip;
179                            connectorModel.ConnectorOrientation = ConnectorOrientation.West;
180                            EventInfo eventinfo = Plugin.GetType().GetEvent(dynamicPropertyInfoAttribute.UpdateDynamicPropertiesEvent);
181                            connectorModel.IsDynamic = true;
182                            connectorModel.DynamicGetterName = dynamicPropertyInfoAttribute.MethodGetValue;
183                            connectorModel.DynamicSetterName = dynamicPropertyInfoAttribute.MethodSetValue;
184                            eventinfo.AddEventHandler(Plugin, new DynamicPropertiesChanged(connectorModel.PropertyTypeChangedOnPlugin));
185                            InputConnectors.Add(connectorModel);
186                            WorkspaceModel.AllConnectorModels.Add(connectorModel);
187                        }
188                        else if (dynamicProperty.PInfo.Direction.Equals(Direction.OutputData))
189                        {
190                            ConnectorModel connectorModel = new ConnectorModel();
191                            connectorModel.ConnectorType = dynamicProperty.Type;
192                            connectorModel.WorkspaceModel = WorkspaceModel;
193                            connectorModel.PluginModel = this;
194                            connectorModel.IsMandatory = dynamicProperty.PInfo.Mandatory;
195                            connectorModel.PropertyName = dynamicProperty.Name;
196                            connectorModel.ToolTip = dynamicProperty.PInfo.ToolTip;
197                            connectorModel.ConnectorOrientation = ConnectorOrientation.East;
198                            EventInfo eventinfo = Plugin.GetType().GetEvent(dynamicPropertyInfoAttribute.UpdateDynamicPropertiesEvent);
199                            eventinfo.AddEventHandler(Plugin, new DynamicPropertiesChanged(connectorModel.PropertyTypeChangedOnPlugin));
200                            connectorModel.IsDynamic = true;
201                            connectorModel.DynamicGetterName = dynamicPropertyInfoAttribute.MethodGetValue;
202                            connectorModel.DynamicSetterName = dynamicPropertyInfoAttribute.MethodSetValue;
203                            connectorModel.Outgoing = true;
204                            Plugin.PropertyChanged += connectorModel.PropertyChangedOnPlugin;
205                            OutputConnectors.Add(connectorModel);
206                            WorkspaceModel.AllConnectorModels.Add(connectorModel);
207
208                        }
209                    }
210                }
211            }
212        }
213        /// <summary>
214        /// Get the Image of the Plugin
215        /// </summary>
216        /// <returns></returns>
217        public Image getImage()
218        {
219            return Plugin.GetImage(imageIndex);
220        }
221
222        /// <summary>
223        /// Returns the Presentation of the wrapped IPlugin
224        /// </summary>
225        public UserControl PluginPresentation
226        {
227            get
228            {
229                if(this.Plugin.Presentation != null){
230                    return this.Plugin.Presentation;
231                }else{
232                    return this.Plugin.QuickWatchPresentation;
233                }
234            }
235        }
236             
237        /// <summary>
238        /// Should be called by the UI-Thread to paint changes of the PluginModel
239        /// </summary>
240        public void paint()
241        {
242            //Enter some Code which calls the paint method of the IPlugin
243        }
244
245        /// <summary>
246        /// Checks wether this PluginModel is executable or not and sets the isExecutable bool
247        ///
248        /// There are 3 ways in that a plugin can be executable:
249        ///     1. All mandatory inputs are set + all outputs are "free"
250        ///     2. There are no mandatory inputs and at least one non-mandatory input is set + all outputs are "free"
251        ///     3. There are no inputs + all outputs are "free"
252        /// </summary>
253        public void checkExecutable(ProtocolBase protocolBase)
254        {
255            //We do not execute Plugins with Errors
256            if (this.State == PluginModelState.Error)
257            {
258                return;
259            }
260
261            bool AtLeastOneInputSet = false;
262            //First test if every mandatory Connector has data
263            //or one non-mandatory input has data
264            foreach (ConnectorModel connectorModel in this.InputConnectors)
265            {
266                if ((connectorModel.IsMandatory /*|| connectorModel.InputConnection != null*/) && !connectorModel.HasData)
267                {
268                    return;
269                }
270                else if (connectorModel.HasData)
271                {
272                    AtLeastOneInputSet = true;
273                }
274            }
275
276            if (AtLeastOneInputSet)
277            {
278                MessageExecution msg = new MessageExecution();
279                msg.PluginModel = this;
280               
281                //protocolBase is set at Startup of the ExecutionEngine
282                //but it could be that we have an event before setting
283                //of the protocl base (triggered by user clicking on
284                //a plugins presentation (button or so))
285                if (protocolBase != null)
286                {
287                    protocolBase.BroadcastMessageReliably(msg);
288                }
289            }
290            return;
291        }
292
293        /// <summary>
294        /// Progress of the plugin changed
295        /// </summary>
296        /// <param name="sender"></param>
297        /// <param name="args"></param>
298        public void PluginProgressChanged(IPlugin sender, PluginProgressEventArgs args)
299        {
300            //Calculate % of the plugins process
301            this.PercentageFinished = args.Value / args.Max;
302            //Tell the ExecutionEngine that this plugin needs a gui update
303            this.GuiNeedsUpdate = true;
304        }
305
306        /// <summary>
307        /// Status of the plugin changed
308        /// </summary>
309        /// <param name="sender"></param>
310        /// <param name="args"></param>
311        public void PluginStatusChanged(IPlugin sender, StatusEventArgs args)
312        {
313            if (args.StatusChangedMode == StatusChangedMode.ImageUpdate)
314            {
315                this.imageIndex = args.ImageIndex;
316            }
317               
318            if (this.WorkspaceModel.WorkspaceManagerEditor.isExecuting())
319            {
320                this.GuiNeedsUpdate = true;
321            }
322            else
323            {
324                this.WorkspaceModel.WorkspaceManagerEditor.Presentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
325                {
326                    this.UpdateableView.update();
327                }, null);
328            }           
329        }
330
331        /// <summary>
332        /// The pluginProtocol of the current ExecutionEngine run to set/get
333        /// </summary>
334        public PluginProtocol PluginProtocol {
335            get { return pluginProtocol; }
336            set { pluginProtocol = value;}
337        }
338    }
339
340    public enum PluginModelState{
341        Normal,
342        Warning,
343        Error
344    }
345}
Note: See TracBrowser for help on using the repository browser.