Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 9011 was 9011, checked in by mkommend, 11 years ago

#1991: Adapted OperatorGraphVisualization to ignore warnings regarding the obsolete attribute and adapted to the new BidirectionalDictionary if possible.

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