Free cookie consent management tool by TermsFeed Policy Generator

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

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

completly refactored the graph visualization (ticket #867)

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