Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 2935 was 2935, checked in by mkommend, 15 years ago

added visual indication for operator breakpoints (ticket #867)

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