Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/OperatorGraphVisualization/OperatorGraphVisualizationInfo.cs @ 3422

Last change on this file since 3422 was 3422, checked in by mkommend, 14 years ago
  • corrected bugs in operator graph visualization (ticket #867)
  • changed multi call operators in graph visualization (ticket #979)
File size: 21.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.Core;
27using Netron.Diagramming.Core;
28using System.Drawing;
29using HeuristicLab.Collections;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31using HeuristicLab.Common;
32
33namespace HeuristicLab.Operators.Views.GraphVisualization {
34  [StorableClass]
35  public sealed class OperatorGraphVisualizationInfo : GraphVisualizationInfo {
36    [Storable]
37    private BidirectionalLookup<IOperator, IOperatorShapeInfo> operatorShapeInfoMapping;
38    private BidirectionalLookup<IOperator, IKeyedItemCollection<string, IParameter>> operatorParameterCollectionMapping;
39    private Dictionary<IParameter, IOperator> parameterOperatorMapping;
40
41    private OperatorGraphVisualizationInfo()
42      : base() {
43      this.operatorShapeInfoMapping = new BidirectionalLookup<IOperator, IOperatorShapeInfo>();
44      this.operatorParameterCollectionMapping = new BidirectionalLookup<IOperator, IKeyedItemCollection<string, IParameter>>();
45      this.parameterOperatorMapping = new Dictionary<IParameter, IOperator>();
46    }
47
48    [StorableConstructor]
49    private OperatorGraphVisualizationInfo(bool deserializing)
50      : base() {
51      this.operatorParameterCollectionMapping = new BidirectionalLookup<IOperator, IKeyedItemCollection<string, IParameter>>();
52      this.parameterOperatorMapping = new Dictionary<IParameter, IOperator>();
53    }
54
55    public OperatorGraphVisualizationInfo(OperatorGraph operatorGraph)
56      : this() {
57      this.operatorGraph = operatorGraph;
58      this.RegisterOperatorGraphEvents();
59
60      foreach (IOperator op in operatorGraph.Operators)
61        if (!this.operatorShapeInfoMapping.ContainsFirst(op))  //could be added by referencing parameters
62          this.AddOperator(op);
63
64      this.UpdateInitialShape();
65    }
66
67    [StorableHook(HookType.AfterDeserialization)]
68    private void DeserializationHook() {
69      this.operatorGraph.DeserializationFinished += new EventHandler(operatorGraph_DeserializationFinished);
70
71      IOperator op;
72      IOperatorShapeInfo shapeInfo;
73      foreach (KeyValuePair<IOperator, IOperatorShapeInfo> pair in this.operatorShapeInfoMapping.FirstEnumerable) {
74        op = pair.Key;
75        shapeInfo = pair.Value;
76        shapeInfo.Icon = new Bitmap(op.ItemImage);
77        this.RegisterOperatorEvents(op);
78        this.operatorParameterCollectionMapping.Add(op, op.Parameters);
79      }
80
81      foreach (IOperator oper in this.operatorShapeInfoMapping.FirstValues) {
82        foreach (IParameter param in oper.Parameters) {
83          IValueParameter opParam = param as IValueParameter;
84          this.parameterOperatorMapping.Add(param, oper);
85          if (opParam != null && typeof(IOperator).IsAssignableFrom(param.DataType))
86            this.RegisterOperatorParameterEvents(opParam);
87          else
88            this.RegisterParameterEvents(param);
89        }
90      }
91    }
92
93    private void operatorGraph_DeserializationFinished(object sender, EventArgs e) {
94      this.RegisterOperatorGraphEvents();
95      if (this.operatorGraph.InitialOperator != null) {
96        IOperatorShapeInfo newInitialShapeInfo = this.operatorShapeInfoMapping.GetByFirst(this.operatorGraph.InitialOperator);
97        if (newInitialShapeInfo != null) {
98          oldInitialShapeColor = newInitialShapeInfo.Color;
99          newInitialShapeInfo.Color = Color.LightGreen;
100        }
101        oldInitialShape = this.InitialShape;
102        this.OnInitialShapeChanged();
103      }
104      this.operatorGraph.DeserializationFinished -= new EventHandler(operatorGraph_DeserializationFinished);
105    }
106
107    public override IDeepCloneable Clone(Cloner cloner) {
108      OperatorGraphVisualizationInfo clone = (OperatorGraphVisualizationInfo)base.Clone(cloner);
109      clone.operatorGraph = (OperatorGraph)cloner.Clone(this.operatorGraph);
110      clone.RegisterOperatorGraphEvents();
111      clone.oldInitialShape = (IOperatorShapeInfo)cloner.Clone(this.oldInitialShape);
112      clone.oldInitialShapeColor = this.oldInitialShapeColor;
113
114      IOperator op;
115      IOperatorShapeInfo shapeInfo;
116      foreach (KeyValuePair<IOperator, IOperatorShapeInfo> pair in this.operatorShapeInfoMapping.FirstEnumerable) {
117        op = (IOperator)cloner.Clone(pair.Key);
118        shapeInfo = (IOperatorShapeInfo)cloner.Clone(pair.Value);
119        clone.RegisterOperatorEvents(op);
120        clone.operatorParameterCollectionMapping.Add(op, pair.Key.Parameters);
121        clone.operatorShapeInfoMapping.Add(op, shapeInfo);
122      }
123
124      foreach (IOperator oper in clone.operatorShapeInfoMapping.FirstValues) {
125        foreach (IParameter param in oper.Parameters) {
126          clone.parameterOperatorMapping.Add(param, oper);
127          IValueParameter opParam = param as IValueParameter;
128          if (opParam != null && typeof(IOperator).IsAssignableFrom(param.DataType))
129            clone.RegisterOperatorParameterEvents(opParam);
130          else
131            clone.RegisterParameterEvents(param);
132        }
133      }
134      if (this.operatorGraph.InitialOperator != null) {
135        IOperatorShapeInfo newInitialShapeInfo = this.operatorShapeInfoMapping.GetByFirst(this.operatorGraph.InitialOperator);
136        if (newInitialShapeInfo != null) {
137          oldInitialShapeColor = newInitialShapeInfo.Color;
138          newInitialShapeInfo.Color = Color.LightGreen;
139        }
140        oldInitialShape = this.InitialShape;
141        this.OnInitialShapeChanged();
142      }
143      return clone;
144    }
145
146    internal IOperator GetOperatorForShapeInfo(IOperatorShapeInfo shapeInfo) {
147      return this.operatorShapeInfoMapping.GetBySecond(shapeInfo);
148    }
149
150    private void operatorGraph_InitialOperatorChanged(object sender, EventArgs e) {
151      this.UpdateInitialShape();
152    }
153
154    private void UpdateInitialShape() {
155      IOperatorShapeInfo old = this.oldInitialShape as OperatorShapeInfo;
156      if (old != null)
157        old.Color = oldInitialShapeColor;
158
159      OperatorShapeInfo newInitialShapeInfo = this.InitialShape as OperatorShapeInfo;
160      if (newInitialShapeInfo != null) {
161        oldInitialShapeColor = newInitialShapeInfo.Color;
162        newInitialShapeInfo.Color = Color.LightGreen;
163      }
164
165      oldInitialShape = this.InitialShape;
166      this.OnInitialShapeChanged();
167    }
168
169    private IShapeInfo oldInitialShape;
170    private Color oldInitialShapeColor;
171    public override IShapeInfo InitialShape {
172      get {
173        IOperator op = this.operatorGraph.InitialOperator;
174        if (op == null)
175          return null;
176        return this.operatorShapeInfoMapping.GetByFirst(op);
177      }
178      set {
179        if (value == null)
180          this.OperatorGraph.InitialOperator = null;
181        else {
182          IOperatorShapeInfo shapeInfo = (IOperatorShapeInfo)value;
183          this.OperatorGraph.InitialOperator = this.operatorShapeInfoMapping.GetBySecond(shapeInfo);
184        }
185      }
186    }
187
188    [Storable]
189    private OperatorGraph operatorGraph;
190    public OperatorGraph OperatorGraph {
191      get { return this.operatorGraph; }
192    }
193
194    private void RegisterOperatorGraphEvents() {
195      this.operatorGraph.InitialOperatorChanged += new EventHandler(operatorGraph_InitialOperatorChanged);
196      this.operatorGraph.Operators.ItemsAdded += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperator>(Operators_ItemsAdded);
197      this.operatorGraph.Operators.ItemsRemoved += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperator>(Operators_ItemsRemoved);
198      this.operatorGraph.Operators.CollectionReset += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperator>(Operators_CollectionReset);
199    }
200
201    private void DeregisterOperatorGraphEvents() {
202      this.operatorGraph.InitialOperatorChanged -= new EventHandler(operatorGraph_InitialOperatorChanged);
203      this.operatorGraph.Operators.ItemsAdded -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperator>(Operators_ItemsAdded);
204      this.operatorGraph.Operators.ItemsRemoved -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperator>(Operators_ItemsRemoved);
205      this.operatorGraph.Operators.CollectionReset -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperator>(Operators_CollectionReset);
206    }
207
208    #region methods to manipulate operatorgraph by the shape info
209    internal void AddShapeInfo(IOperator op, IOperatorShapeInfo shapeInfo) {
210      this.RegisterOperatorEvents(op);
211      this.operatorParameterCollectionMapping.Add(op, op.Parameters);
212      this.operatorShapeInfoMapping.Add(op, shapeInfo);
213      this.shapeInfos.Add(shapeInfo);
214
215      foreach (IParameter param in op.Parameters)
216        this.AddParameter(op, param);
217
218      this.operatorGraph.Operators.Add(op);
219    }
220
221    public override void RemoveShapeInfo(IShapeInfo shapeInfo) {
222      IOperatorShapeInfo opShapeInfo = (IOperatorShapeInfo)shapeInfo;
223      if (this.operatorShapeInfoMapping.ContainsSecond(opShapeInfo)) {
224        IOperator op = this.operatorShapeInfoMapping.GetBySecond(opShapeInfo);
225        this.operatorGraph.Operators.Remove(op);
226      }
227    }
228
229    public override void RemoveConnectionInfo(IConnectionInfo connectionInfo) {
230      IOperatorShapeInfo shapeInfo = (IOperatorShapeInfo)connectionInfo.From;
231      IOperator op = this.operatorShapeInfoMapping.GetBySecond(shapeInfo);
232      IValueParameter param = (IValueParameter)op.Parameters[connectionInfo.ConnectorFrom];
233      param.Value = null;
234    }
235
236    public override void AddConnectionInfo(IConnectionInfo connectionInfo) {
237      IOperatorShapeInfo shapeInfo = (IOperatorShapeInfo)connectionInfo.From;
238      IOperator op = this.operatorShapeInfoMapping.GetBySecond(shapeInfo);
239      IValueParameter param = (IValueParameter)op.Parameters.Where(p => p.Name == connectionInfo.ConnectorFrom).Single();
240      IOperatorShapeInfo shapeInfoTo = (IOperatorShapeInfo)connectionInfo.To;
241      IOperator opTo = this.operatorShapeInfoMapping.GetBySecond(shapeInfoTo);
242      param.Value = opTo;
243    }
244    #endregion
245
246    #region operator events
247    private void AddOperator(IOperator op) {
248      if (!this.operatorShapeInfoMapping.ContainsFirst(op)) {
249        this.RegisterOperatorEvents(op);
250        IOperatorShapeInfo shapeInfo = OperatorShapeInfoFactory.CreateOperatorShapeInfo(op);
251        this.operatorParameterCollectionMapping.Add(op, op.Parameters);
252        this.operatorShapeInfoMapping.Add(op, shapeInfo);
253        this.shapeInfos.Add(shapeInfo);
254        foreach (IParameter param in op.Parameters)
255          this.AddParameter(op, param);
256      }
257    }
258    private void RemoveOperator(IOperator op) {
259      this.DeregisterOperatorEvents(op);
260      foreach (IParameter param in op.Parameters)
261        this.RemoveParameter(op, param);
262
263      IOperatorShapeInfo shapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
264      this.operatorParameterCollectionMapping.RemoveByFirst(op);
265      this.operatorShapeInfoMapping.RemoveByFirst(op);
266      this.shapeInfos.Remove(shapeInfo);
267    }
268
269    private void OperatorBreakpointChanged(object sender, EventArgs e) {
270      IOperator op = (IOperator)sender;
271      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
272      if (op.Breakpoint) {
273        operatorShapeInfo.LineColor = Color.Red;
274        operatorShapeInfo.LineWidth = 2;
275      } else {
276        operatorShapeInfo.LineColor = Color.Black;
277        operatorShapeInfo.LineWidth = 1;
278      }
279    }
280
281    private void OperatorItemImageChanged(object sender, EventArgs e) {
282      IOperator op = (IOperator)sender;
283      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
284      operatorShapeInfo.Icon = new Bitmap(op.ItemImage);
285    }
286
287    private void OperatorNameChanged(object sender, EventArgs e) {
288      IOperator op = (IOperator)sender;
289      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
290      operatorShapeInfo.Title = op.Name;
291    }
292
293    private void Operators_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
294      foreach (IOperator op in e.Items)
295        this.AddOperator(op);
296    }
297    private void Operators_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
298      foreach (IOperator op in e.Items)
299        this.RemoveOperator(op);
300    }
301    private void Operators_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
302      foreach (IOperator op in e.OldItems)
303        this.RemoveOperator(op);
304      foreach (IOperator op in e.Items)
305        this.AddOperator(op);
306    }
307
308    private void RegisterOperatorEvents(IOperator op) {
309      op.Parameters.ItemsAdded += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
310      op.Parameters.ItemsRemoved += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
311      op.Parameters.ItemsReplaced += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
312      op.Parameters.CollectionReset += new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
313      op.NameChanged += new EventHandler(OperatorNameChanged);
314      op.ItemImageChanged += new EventHandler(OperatorItemImageChanged);
315      op.BreakpointChanged += new EventHandler(OperatorBreakpointChanged);
316    }
317
318    private void DeregisterOperatorEvents(IOperator op) {
319      op.Parameters.ItemsAdded -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
320      op.Parameters.ItemsRemoved -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
321      op.Parameters.ItemsReplaced -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
322      op.Parameters.CollectionReset -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
323      op.NameChanged -= new EventHandler(OperatorNameChanged);
324      op.ItemImageChanged -= new EventHandler(OperatorItemImageChanged);
325      op.BreakpointChanged -= new EventHandler(OperatorBreakpointChanged);
326    }
327    #endregion
328
329    #region parameter events
330    private void AddParameter(IOperator op, IParameter param) {
331      this.parameterOperatorMapping.Add(param, op);
332      IValueParameter opParam = param as IValueParameter;
333      if (opParam != null && typeof(IOperator).IsAssignableFrom(param.DataType)) {
334        this.RegisterOperatorParameterEvents(opParam);
335        IOperatorShapeInfo shapeInfoFrom = this.operatorShapeInfoMapping.GetByFirst(op);
336        shapeInfoFrom.AddConnector(param.Name);
337
338        if (opParam.Value != null) {
339          if (!this.operatorShapeInfoMapping.ContainsFirst((IOperator)opParam.Value))
340            this.AddOperator((IOperator)opParam.Value);
341          IOperatorShapeInfo shapeInfoTo = this.operatorShapeInfoMapping.GetByFirst((IOperator)opParam.Value);
342          this.connectionInfos.Add(new ConnectionInfo(shapeInfoFrom, param.Name, shapeInfoTo, OperatorShapeInfoFactory.PredecessorConnector));
343        }
344      } else
345        this.RegisterParameterEvents(param);
346    }
347
348    private void RemoveParameter(IOperator op, IParameter param) {
349      IValueParameter opParam = param as IValueParameter;
350      if (opParam != null && typeof(IOperator).IsAssignableFrom(param.DataType)) {
351        this.DeregisterOperatorParameterEvents(opParam);
352        IOperatorShapeInfo shapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
353        this.connectionInfos.RemoveWhere(c => c.From == shapeInfo && c.ConnectorFrom == param.Name);
354        this.connectionInfos.RemoveWhere(c => c.To == shapeInfo && c.ConnectorTo == param.Name);
355        shapeInfo.RemoveConnector(param.Name);
356      } else
357        this.DeregisterParameterEvents(param);
358
359      this.parameterOperatorMapping.Remove(param);
360    }
361
362    private void opParam_ValueChanged(object sender, EventArgs e) {
363      IValueParameter opParam = (IValueParameter)sender;
364      IOperator op = this.parameterOperatorMapping[opParam];
365      IOperatorShapeInfo shapeInfoFrom = this.operatorShapeInfoMapping.GetByFirst(op);
366      KeyValuePair<IOperatorShapeInfo, string> connectionFrom = new KeyValuePair<IOperatorShapeInfo, string>(shapeInfoFrom, opParam.Name);
367
368      this.connectionInfos.RemoveWhere(c => c.From == shapeInfoFrom && c.ConnectorFrom == opParam.Name);
369      if (opParam.Value != null) {
370        if (!this.operatorShapeInfoMapping.ContainsFirst((IOperator)opParam.Value))
371          this.AddOperator((IOperator)opParam.Value);
372        IOperatorShapeInfo shapeInfoTo = this.operatorShapeInfoMapping.GetByFirst((IOperator)opParam.Value);
373        base.AddConnectionInfo(new ConnectionInfo(shapeInfoFrom, opParam.Name, shapeInfoTo, OperatorShapeInfoFactory.PredecessorConnector));
374      }
375    }
376
377    private void Parameters_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
378      IKeyedItemCollection<string, IParameter> parameterCollection = sender as IKeyedItemCollection<string, IParameter>;
379      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
380      foreach (IParameter param in e.Items)
381        AddParameter(op, param);
382      this.UpdateParameterLabels(op);
383    }
384    private void Parameters_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
385      IKeyedItemCollection<string, IParameter> parameterCollection = sender as IKeyedItemCollection<string, IParameter>;
386      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
387      foreach (IParameter param in e.Items)
388        RemoveParameter(op, param);
389      this.UpdateParameterLabels(op);
390    }
391    private void Parameters_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
392      IKeyedItemCollection<string, IParameter> parameterCollection = sender as IKeyedItemCollection<string, IParameter>;
393      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
394      foreach (IParameter param in e.OldItems)
395        RemoveParameter(op, param);
396      foreach (IParameter param in e.Items)
397        AddParameter(op, param);
398      this.UpdateParameterLabels(op);
399    }
400    private void Parameters_CollectionReset(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
401      IKeyedItemCollection<string, IParameter> parameterCollection = sender as IKeyedItemCollection<string, IParameter>;
402      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
403      foreach (IParameter param in e.OldItems)
404        RemoveParameter(op, param);
405      foreach (IParameter param in e.Items)
406        AddParameter(op, param);
407      this.UpdateParameterLabels(op);
408    }
409
410    private void RegisterOperatorParameterEvents(IValueParameter opParam) {
411      opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
412    }
413    private void DeregisterOperatorParameterEvents(IValueParameter opParam) {
414      opParam.ValueChanged -= new EventHandler(opParam_ValueChanged);
415    }
416    private void RegisterParameterEvents(IParameter param) {
417      param.ToStringChanged += new EventHandler(param_ToStringChanged);
418      param.NameChanged += new EventHandler(param_NameChanged);
419    }
420    private void DeregisterParameterEvents(IParameter param) {
421      param.ToStringChanged -= new EventHandler(param_ToStringChanged);
422      param.NameChanged -= new EventHandler(param_NameChanged);
423    }
424
425    private void param_NameChanged(object sender, EventArgs e) {
426      IParameter param = (IParameter)sender;
427      IOperator op = this.parameterOperatorMapping[param];
428      this.UpdateParameterLabels(op);
429    }
430    private void param_ToStringChanged(object sender, EventArgs e) {
431      IParameter param = (IParameter)sender;
432      IOperator op = this.parameterOperatorMapping[param];
433      this.UpdateParameterLabels(op);
434    }
435
436    private void UpdateParameterLabels(IOperator op) {
437      IEnumerable<IParameter> parameters = op.Parameters.Where(p => !(p is IValueParameter && typeof(IOperator).IsAssignableFrom(p.DataType)));
438      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
439      if (parameters.Count() > 0)
440        operatorShapeInfo.UpdateLabels(parameters.Select(p => p.ToString()));
441      else
442        operatorShapeInfo.UpdateLabels(new List<string>());
443    }
444    #endregion
445  }
446}
Note: See TracBrowser for help on using the repository browser.