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

Last change on this file since 1700 was 1700, checked in by kopal, 11 years ago
  • WorkspaceManager now allows multiple Connections on InputConnectors
  • Created own Gears4Net Scheduler which implements flow control in WorkspaceManagers ExecutionEngine to support loops
  • some small bugfixes
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.Name = propertyInfoAttribute.PropertyName;
142                        connectorModel.ToolTip = propertyInfoAttribute.ToolTip;
143                        connectorModel.ConnectorOrientation = ConnectorOrientation.West;
144                        InputConnectors.Add(connectorModel);
145                        WorkspaceModel.AllConnectorModels.Add(connectorModel);
146                    }
147                    else if (propertyInfoAttribute.Direction.Equals(Direction.OutputData))
148                    {
149                        ConnectorModel connectorModel = new ConnectorModel();
150                        connectorModel.ConnectorType = propertyInfoAttribute.PropertyInfo.PropertyType;
151                        connectorModel.WorkspaceModel = WorkspaceModel;
152                        connectorModel.PluginModel = this;
153                        connectorModel.IsMandatory = propertyInfoAttribute.Mandatory;
154                        connectorModel.PropertyName = propertyInfoAttribute.PropertyName;
155                        connectorModel.Name = propertyInfoAttribute.PropertyName;
156                        connectorModel.ToolTip = propertyInfoAttribute.ToolTip;
157                        connectorModel.ConnectorOrientation = ConnectorOrientation.East;
158                        connectorModel.Outgoing = true;
159                        Plugin.PropertyChanged += connectorModel.PropertyChangedOnPlugin;
160                        OutputConnectors.Add(connectorModel);
161                        WorkspaceModel.AllConnectorModels.Add(connectorModel);
162                    }
163                }
164
165                Dictionary<string, DynamicProperty> dictionary = Plugin.GetDynamicPropertyList();
166                if (dictionary != null)
167                {
168                    DynamicPropertyInfoAttribute dynamicPropertyInfoAttribute = Plugin.GetDynamicPropertyInfo();
169                    foreach (DynamicProperty dynamicProperty in dictionary.Values)
170                    {
171
172                        if (dynamicProperty.PInfo.Direction.Equals(Direction.InputData))
173                        {
174                            ConnectorModel connectorModel = new ConnectorModel();
175                            connectorModel.ConnectorType = dynamicProperty.Type;
176                            connectorModel.WorkspaceModel = WorkspaceModel;
177                            connectorModel.PluginModel = this;
178                            connectorModel.IsMandatory = dynamicProperty.PInfo.Mandatory;
179                            connectorModel.PropertyName = dynamicProperty.Name;
180                            connectorModel.Name = dynamicProperty.Name;
181                            connectorModel.ToolTip = dynamicProperty.PInfo.ToolTip;
182                            connectorModel.ConnectorOrientation = ConnectorOrientation.West;
183                            EventInfo eventinfo = Plugin.GetType().GetEvent(dynamicPropertyInfoAttribute.UpdateDynamicPropertiesEvent);
184                            connectorModel.IsDynamic = true;
185                            connectorModel.DynamicGetterName = dynamicPropertyInfoAttribute.MethodGetValue;
186                            connectorModel.DynamicSetterName = dynamicPropertyInfoAttribute.MethodSetValue;
187                            eventinfo.AddEventHandler(Plugin, new DynamicPropertiesChanged(connectorModel.PropertyTypeChangedOnPlugin));
188                            InputConnectors.Add(connectorModel);
189                            WorkspaceModel.AllConnectorModels.Add(connectorModel);
190                        }
191                        else if (dynamicProperty.PInfo.Direction.Equals(Direction.OutputData))
192                        {
193                            ConnectorModel connectorModel = new ConnectorModel();
194                            connectorModel.ConnectorType = dynamicProperty.Type;
195                            connectorModel.WorkspaceModel = WorkspaceModel;
196                            connectorModel.PluginModel = this;
197                            connectorModel.IsMandatory = dynamicProperty.PInfo.Mandatory;
198                            connectorModel.PropertyName = dynamicProperty.Name;
199                            connectorModel.Name = dynamicProperty.Name;
200                            connectorModel.ToolTip = dynamicProperty.PInfo.ToolTip;
201                            connectorModel.ConnectorOrientation = ConnectorOrientation.East;
202                            EventInfo eventinfo = Plugin.GetType().GetEvent(dynamicPropertyInfoAttribute.UpdateDynamicPropertiesEvent);
203                            eventinfo.AddEventHandler(Plugin, new DynamicPropertiesChanged(connectorModel.PropertyTypeChangedOnPlugin));
204                            connectorModel.IsDynamic = true;
205                            connectorModel.DynamicGetterName = dynamicPropertyInfoAttribute.MethodGetValue;
206                            connectorModel.DynamicSetterName = dynamicPropertyInfoAttribute.MethodSetValue;
207                            connectorModel.Outgoing = true;
208                            Plugin.PropertyChanged += connectorModel.PropertyChangedOnPlugin;
209                            OutputConnectors.Add(connectorModel);
210                            WorkspaceModel.AllConnectorModels.Add(connectorModel);
211
212                        }
213                    }
214                }
215            }
216        }
217        /// <summary>
218        /// Get the Image of the Plugin
219        /// </summary>
220        /// <returns></returns>
221        public Image getImage()
222        {
223            return Plugin.GetImage(imageIndex);
224        }
225
226        /// <summary>
227        /// Returns the Presentation of the wrapped IPlugin
228        /// </summary>
229        public UserControl PluginPresentation
230        {
231            get
232            {
233                if(this.Plugin.Presentation != null){
234                    return this.Plugin.Presentation;
235                }else{
236                    return this.Plugin.QuickWatchPresentation;
237                }
238            }
239        }
240             
241        /// <summary>
242        /// Should be called by the UI-Thread to paint changes of the PluginModel
243        /// </summary>
244        public void paint()
245        {
246            //Enter some Code which calls the paint method of the IPlugin
247        }
248
249        /// <summary>
250        /// Checks wether this PluginModel is executable or not and sets the isExecutable bool
251        ///
252        /// There are 3 ways in that a plugin can be executable:
253        ///     1. All mandatory inputs are set + all outputs are "free"
254        ///     2. There are no mandatory inputs and at least one non-mandatory input is set + all outputs are "free"
255        ///     3. There are no inputs + all outputs are "free"
256        /// </summary>
257        public void checkExecutable(ProtocolBase protocolBase)
258        {
259            //We do not execute Plugins with Errors
260            if (this.State == PluginModelState.Error)
261            {
262                return;
263            }
264           
265            //First test if every mandatory Connector has data
266            //or one non-mandatory input has data
267            foreach (ConnectorModel connectorModel in this.InputConnectors)
268            {
269                if ((connectorModel.IsMandatory || connectorModel.InputConnections.Count > 0) && !connectorModel.HasData)
270                {
271                    return;
272                }               
273            }
274
275            MessageExecution msg = new MessageExecution();
276            msg.PluginModel = this;
277               
278            //protocolBase is set at Startup of the ExecutionEngine
279            //but it could be that we have an event before setting
280            //of the protocl base (triggered by user clicking on
281            //a plugins presentation (button or so))
282            if (protocolBase != null)
283            {
284                protocolBase.BroadcastMessageReliably(msg);
285            }
286
287            return;
288        }
289
290        /// <summary>
291        /// Progress of the plugin changed
292        /// </summary>
293        /// <param name="sender"></param>
294        /// <param name="args"></param>
295        public void PluginProgressChanged(IPlugin sender, PluginProgressEventArgs args)
296        {
297            //Calculate % of the plugins process
298            this.PercentageFinished = args.Value / args.Max;
299            //Tell the ExecutionEngine that this plugin needs a gui update
300            this.GuiNeedsUpdate = true;
301        }
302
303        /// <summary>
304        /// Status of the plugin changed
305        /// </summary>
306        /// <param name="sender"></param>
307        /// <param name="args"></param>
308        public void PluginStatusChanged(IPlugin sender, StatusEventArgs args)
309        {
310            if (args.StatusChangedMode == StatusChangedMode.ImageUpdate)
311            {
312                this.imageIndex = args.ImageIndex;
313            }
314               
315            if (this.WorkspaceModel.WorkspaceManagerEditor.isExecuting())
316            {
317                this.GuiNeedsUpdate = true;
318            }
319            else
320            {
321                this.WorkspaceModel.WorkspaceManagerEditor.Presentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
322                {
323                    this.UpdateableView.update();
324                }, null);
325            }           
326        }
327
328        /// <summary>
329        /// The pluginProtocol of the current ExecutionEngine run to set/get
330        /// </summary>
331        public PluginProtocol PluginProtocol {
332            get { return pluginProtocol; }
333            set { pluginProtocol = value;}
334        }
335    }
336
337    public enum PluginModelState{
338        Normal,
339        Warning,
340        Error
341    }
342}
Note: See TracBrowser for help on using the repository browser.