Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/Model/GraphVisualizationInfo.cs @ 3376

Last change on this file since 3376 was 3376, checked in by swagner, 14 years ago

Moved interfaces and classes for deep cloning from HeuristicLab.Core to HeuristicLab.Common (#975).

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