Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3523 was 3514, checked in by mkommend, 14 years ago

implemented application review comments from abeham (ticket #867)

File size: 21.2 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      IOperatorShapeInfo shapeInfoTo = (IOperatorShapeInfo)connectionInfo.To;
240      IOperator opTo = this.operatorShapeInfoMapping.GetBySecond(shapeInfoTo);
241      IValueParameter param = (IValueParameter)op.Parameters.Where(p => p.Name == connectionInfo.ConnectorFrom).SingleOrDefault();
242      if (param != null)
243        param.Value = opTo;
244    }
245    #endregion
246
247    #region operator events
248    private void AddOperator(IOperator op) {
249      if (!this.operatorShapeInfoMapping.ContainsFirst(op)) {
250        this.RegisterOperatorEvents(op);
251        IOperatorShapeInfo shapeInfo = OperatorShapeInfoFactory.CreateOperatorShapeInfo(op);
252        this.operatorParameterCollectionMapping.Add(op, op.Parameters);
253        this.operatorShapeInfoMapping.Add(op, shapeInfo);
254        this.shapeInfos.Add(shapeInfo);
255        foreach (IParameter param in op.Parameters)
256          this.AddParameter(op, param);
257      }
258    }
259    private void RemoveOperator(IOperator op) {
260      this.DeregisterOperatorEvents(op);
261      foreach (IParameter param in op.Parameters)
262        this.RemoveParameter(op, param);
263
264      IOperatorShapeInfo shapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
265      this.operatorParameterCollectionMapping.RemoveByFirst(op);
266      this.operatorShapeInfoMapping.RemoveByFirst(op);
267      this.shapeInfos.Remove(shapeInfo);
268    }
269
270    private void OperatorBreakpointChanged(object sender, EventArgs e) {
271      IOperator op = (IOperator)sender;
272      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
273      if (op.Breakpoint) {
274        operatorShapeInfo.LineColor = Color.Red;
275        operatorShapeInfo.LineWidth = 2;
276      } else {
277        operatorShapeInfo.LineColor = Color.Black;
278        operatorShapeInfo.LineWidth = 1;
279      }
280    }
281
282    private void OperatorItemImageChanged(object sender, EventArgs e) {
283      IOperator op = (IOperator)sender;
284      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
285      operatorShapeInfo.Icon = new Bitmap(op.ItemImage);
286    }
287
288    private void OperatorNameChanged(object sender, EventArgs e) {
289      IOperator op = (IOperator)sender;
290      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
291      operatorShapeInfo.Title = op.Name;
292    }
293
294    private void Operators_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
295      foreach (IOperator op in e.Items)
296        this.AddOperator(op);
297    }
298    private void Operators_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
299      foreach (IOperator op in e.Items)
300        this.RemoveOperator(op);
301    }
302    private void Operators_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
303      foreach (IOperator op in e.OldItems)
304        this.RemoveOperator(op);
305      foreach (IOperator op in e.Items)
306        this.AddOperator(op);
307    }
308
309    private void RegisterOperatorEvents(IOperator op) {
310      op.Parameters.ItemsAdded += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
311      op.Parameters.ItemsRemoved += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
312      op.Parameters.ItemsReplaced += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
313      op.Parameters.CollectionReset += new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
314      op.NameChanged += new EventHandler(OperatorNameChanged);
315      op.ItemImageChanged += new EventHandler(OperatorItemImageChanged);
316      op.BreakpointChanged += new EventHandler(OperatorBreakpointChanged);
317    }
318
319    private void DeregisterOperatorEvents(IOperator op) {
320      op.Parameters.ItemsAdded -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
321      op.Parameters.ItemsRemoved -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
322      op.Parameters.ItemsReplaced -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
323      op.Parameters.CollectionReset -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
324      op.NameChanged -= new EventHandler(OperatorNameChanged);
325      op.ItemImageChanged -= new EventHandler(OperatorItemImageChanged);
326      op.BreakpointChanged -= new EventHandler(OperatorBreakpointChanged);
327    }
328    #endregion
329
330    #region parameter events
331    private void AddParameter(IOperator op, IParameter param) {
332      this.parameterOperatorMapping.Add(param, op);
333      IValueParameter opParam = param as IValueParameter;
334      if (opParam != null && typeof(IOperator).IsAssignableFrom(param.DataType)) {
335        this.RegisterOperatorParameterEvents(opParam);
336        IOperatorShapeInfo shapeInfoFrom = this.operatorShapeInfoMapping.GetByFirst(op);
337        shapeInfoFrom.AddConnector(param.Name);
338
339        if (opParam.Value != null) {
340          if (!this.operatorShapeInfoMapping.ContainsFirst((IOperator)opParam.Value))
341            this.AddOperator((IOperator)opParam.Value);
342          IOperatorShapeInfo shapeInfoTo = this.operatorShapeInfoMapping.GetByFirst((IOperator)opParam.Value);
343          this.connectionInfos.Add(new ConnectionInfo(shapeInfoFrom, param.Name, shapeInfoTo, OperatorShapeInfoFactory.PredecessorConnector));
344        }
345      } else
346        this.RegisterParameterEvents(param);
347    }
348
349    private void RemoveParameter(IOperator op, IParameter param) {
350      IValueParameter opParam = param as IValueParameter;
351      if (opParam != null && typeof(IOperator).IsAssignableFrom(param.DataType)) {
352        this.DeregisterOperatorParameterEvents(opParam);
353        IOperatorShapeInfo shapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
354        this.connectionInfos.RemoveWhere(c => c.From == shapeInfo && c.ConnectorFrom == param.Name);
355        this.connectionInfos.RemoveWhere(c => c.To == shapeInfo && c.ConnectorTo == param.Name);
356        shapeInfo.RemoveConnector(param.Name);
357      } else
358        this.DeregisterParameterEvents(param);
359
360      this.parameterOperatorMapping.Remove(param);
361    }
362
363    private void opParam_ValueChanged(object sender, EventArgs e) {
364      IValueParameter opParam = (IValueParameter)sender;
365      IOperator op = this.parameterOperatorMapping[opParam];
366      IOperatorShapeInfo shapeInfoFrom = this.operatorShapeInfoMapping.GetByFirst(op);
367      KeyValuePair<IOperatorShapeInfo, string> connectionFrom = new KeyValuePair<IOperatorShapeInfo, string>(shapeInfoFrom, opParam.Name);
368
369      this.connectionInfos.RemoveWhere(c => c.From == shapeInfoFrom && c.ConnectorFrom == opParam.Name);
370      if (opParam.Value != null) {
371        if (!this.operatorShapeInfoMapping.ContainsFirst((IOperator)opParam.Value))
372          this.AddOperator((IOperator)opParam.Value);
373        IOperatorShapeInfo shapeInfoTo = this.operatorShapeInfoMapping.GetByFirst((IOperator)opParam.Value);
374        base.AddConnectionInfo(new ConnectionInfo(shapeInfoFrom, opParam.Name, shapeInfoTo, OperatorShapeInfoFactory.PredecessorConnector));
375      }
376    }
377
378    private void Parameters_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
379      IKeyedItemCollection<string, IParameter> parameterCollection = sender as IKeyedItemCollection<string, IParameter>;
380      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
381      foreach (IParameter param in e.Items)
382        AddParameter(op, param);
383      this.UpdateParameterLabels(op);
384    }
385    private void Parameters_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
386      IKeyedItemCollection<string, IParameter> parameterCollection = sender as IKeyedItemCollection<string, IParameter>;
387      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
388      foreach (IParameter param in e.Items)
389        RemoveParameter(op, param);
390      this.UpdateParameterLabels(op);
391    }
392    private void Parameters_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
393      IKeyedItemCollection<string, IParameter> parameterCollection = sender as IKeyedItemCollection<string, IParameter>;
394      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
395      foreach (IParameter param in e.OldItems)
396        RemoveParameter(op, param);
397      foreach (IParameter param in e.Items)
398        AddParameter(op, param);
399      this.UpdateParameterLabels(op);
400    }
401    private void Parameters_CollectionReset(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
402      IKeyedItemCollection<string, IParameter> parameterCollection = sender as IKeyedItemCollection<string, IParameter>;
403      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
404      foreach (IParameter param in e.OldItems)
405        RemoveParameter(op, param);
406      foreach (IParameter param in e.Items)
407        AddParameter(op, param);
408      this.UpdateParameterLabels(op);
409    }
410
411    private void RegisterOperatorParameterEvents(IValueParameter opParam) {
412      opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
413    }
414    private void DeregisterOperatorParameterEvents(IValueParameter opParam) {
415      opParam.ValueChanged -= new EventHandler(opParam_ValueChanged);
416    }
417    private void RegisterParameterEvents(IParameter param) {
418      param.ToStringChanged += new EventHandler(param_ToStringChanged);
419      param.NameChanged += new EventHandler(param_NameChanged);
420    }
421    private void DeregisterParameterEvents(IParameter param) {
422      param.ToStringChanged -= new EventHandler(param_ToStringChanged);
423      param.NameChanged -= new EventHandler(param_NameChanged);
424    }
425
426    private void param_NameChanged(object sender, EventArgs e) {
427      IParameter param = (IParameter)sender;
428      IOperator op = this.parameterOperatorMapping[param];
429      this.UpdateParameterLabels(op);
430    }
431    private void param_ToStringChanged(object sender, EventArgs e) {
432      IParameter param = (IParameter)sender;
433      IOperator op = this.parameterOperatorMapping[param];
434      this.UpdateParameterLabels(op);
435    }
436
437    private void UpdateParameterLabels(IOperator op) {
438      IEnumerable<IParameter> parameters = op.Parameters.Where(p => !(p is IValueParameter && typeof(IOperator).IsAssignableFrom(p.DataType)));
439      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
440      if (parameters.Count() > 0)
441        operatorShapeInfo.UpdateLabels(parameters.Select(p => p.ToString()));
442      else
443        operatorShapeInfo.UpdateLabels(new List<string>());
444    }
445    #endregion
446  }
447}
Note: See TracBrowser for help on using the repository browser.