Free cookie consent management tool by TermsFeed Policy Generator

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

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

added parameters, corrected drag and drop position (ticket #867)

File size: 16.4 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 OperatorNameChanged(object sender, EventArgs e) {
205      IOperator op = (IOperator)sender;
206      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
207      operatorShapeInfo.Title = op.Name;
208    }
209
210    private void Operators_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
211      foreach (IOperator op in e.Items)
212        this.AddOperator(op);
213    }
214    private void Operators_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
215      foreach (IOperator op in e.Items)
216        this.RemoveOperator(op);
217    }
218    private void Operators_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperator> e) {
219      foreach (IOperator op in e.OldItems)
220        this.RemoveOperator(op);
221      foreach (IOperator op in e.Items)
222        this.AddOperator(op);
223    }
224
225    private void RegisterOperatorEvents(IOperator op) {
226      op.Parameters.ItemsAdded += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
227      op.Parameters.ItemsRemoved += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
228      op.Parameters.ItemsReplaced += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
229      op.Parameters.CollectionReset += new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
230      op.NameChanged += new EventHandler(OperatorNameChanged);
231    }
232
233    private void DeregisterOperatorEvents(IOperator op) {
234      op.Parameters.ItemsAdded -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
235      op.Parameters.ItemsRemoved -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
236      op.Parameters.ItemsReplaced -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
237      op.Parameters.CollectionReset -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
238      op.NameChanged -= new EventHandler(OperatorNameChanged);
239    }
240    #endregion
241
242    #region parameter events
243    private void AddParameter(IOperator op, IParameter param) {
244      this.parameterOperatorMapping.Add(param, op);
245      IValueParameter<IOperator> opParam = param as IValueParameter<IOperator>;
246      if (opParam != null) {
247        this.RegisterOperatorParameterEvents(opParam);
248        IOperatorShapeInfo shapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
249        shapeInfo.AddConnector(param.Name);
250
251        if (opParam.Value != null) {
252          if (!this.operatorShapeInfoMapping.ContainsFirst(opParam.Value))
253            this.AddOperator(opParam.Value);
254          this.connections.Add(new KeyValuePair<IOperatorShapeInfo, string>(shapeInfo, param.Name), this.operatorShapeInfoMapping.GetByFirst(opParam.Value));
255        }
256      } else
257        this.RegisterParameterEvents(param);
258    }
259
260    private void RemoveParameter(IOperator op, IParameter param) {
261      IValueParameter<IOperator> opParam = param as IValueParameter<IOperator>;
262      if (opParam != null) {
263        this.DeregisterOperatorParameterEvents(opParam);
264        IOperatorShapeInfo shapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
265        this.connections.Remove(new KeyValuePair<IOperatorShapeInfo, string>(shapeInfo, param.Name));
266        shapeInfo.RemoveConnector(param.Name);
267      } else
268        this.DeregisterParameterEvents(param);
269
270      this.parameterOperatorMapping.Remove(param);
271    }
272
273    private void opParam_ValueChanged(object sender, EventArgs e) {
274      IValueParameter<IOperator> opParam = (IValueParameter<IOperator>)sender;
275      if (opParam != null) {
276        IOperator op = this.parameterOperatorMapping[opParam];
277        IOperatorShapeInfo shapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
278        KeyValuePair<IOperatorShapeInfo, string> connectionFrom = new KeyValuePair<IOperatorShapeInfo, string>(shapeInfo, opParam.Name);
279
280        if (opParam.Value == null)
281          this.connections.Remove(connectionFrom);
282        else {
283          if (!this.operatorShapeInfoMapping.ContainsFirst(opParam.Value))
284            this.AddOperator(opParam.Value);
285          this.connections[connectionFrom] = this.operatorShapeInfoMapping.GetByFirst(opParam.Value);
286        }
287      }
288    }
289
290    private void Parameters_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
291      IObservableKeyedCollection<string, IParameter> parameterCollection = sender as IObservableKeyedCollection<string, IParameter>;
292      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
293      foreach (IParameter param in e.Items)
294        AddParameter(op, param);
295      this.UpdateParameterLabels(op);
296    }
297    private void Parameters_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
298      IObservableKeyedCollection<string, IParameter> parameterCollection = sender as IObservableKeyedCollection<string, IParameter>;
299      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
300      foreach (IParameter param in e.Items)
301        RemoveParameter(op, param);
302      this.UpdateParameterLabels(op);
303    }
304    private void Parameters_ItemsReplaced(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.OldItems)
308        RemoveParameter(op, param);
309      foreach (IParameter param in e.Items)
310        AddParameter(op, param);
311      this.UpdateParameterLabels(op);
312    }
313    private void Parameters_CollectionReset(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
314      IObservableKeyedCollection<string, IParameter> parameterCollection = sender as IObservableKeyedCollection<string, IParameter>;
315      IOperator op = this.operatorParameterCollectionMapping.GetBySecond(parameterCollection);
316      foreach (IParameter param in e.OldItems)
317        RemoveParameter(op, param);
318      foreach (IParameter param in e.Items)
319        AddParameter(op, param);
320      this.UpdateParameterLabels(op);
321    }
322
323    private void RegisterOperatorParameterEvents(IValueParameter<IOperator> opParam) {
324      opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
325    }
326    private void DeregisterOperatorParameterEvents(IValueParameter<IOperator> opParam) {
327      opParam.ValueChanged -= new EventHandler(opParam_ValueChanged);
328    }
329    private void RegisterParameterEvents(IParameter param) {
330      param.ToStringChanged += new EventHandler(param_ToStringChanged);
331      param.NameChanged += new EventHandler(param_NameChanged);
332    }
333    private void DeregisterParameterEvents(IParameter param) {
334      param.ToStringChanged -= new EventHandler(param_ToStringChanged);
335      param.NameChanged -= new EventHandler(param_NameChanged);
336    }
337
338    private void param_NameChanged(object sender, EventArgs e) {
339      IParameter param = (IParameter)sender;
340      IOperator op = this.parameterOperatorMapping[param];
341      this.UpdateParameterLabels(op);
342    }
343    private void param_ToStringChanged(object sender, EventArgs e) {
344      IParameter param = (IParameter)sender;
345      IOperator op = this.parameterOperatorMapping[param];
346      this.UpdateParameterLabels(op);
347    }
348
349    private void UpdateParameterLabels(IOperator op) {
350      IEnumerable<IParameter> parameters = op.Parameters.Where(p => !(p is IValueParameter<IOperator>));
351      IOperatorShapeInfo operatorShapeInfo = this.operatorShapeInfoMapping.GetByFirst(op);
352      if (parameters.Count() > 0)
353        operatorShapeInfo.UpdateLabels(parameters.Select(p => p.ToString()));
354      else
355        operatorShapeInfo.UpdateLabels(new List<string>());
356    }
357    #endregion
358  }
359}
Note: See TracBrowser for help on using the repository browser.