Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/OperatorGraphView.cs @ 2868

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

finished mapping from OperatorGraph to GraphVisualizationInfo (ticket #867)

File size: 19.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.ComponentModel;
25using System.Drawing;
26using System.Data;
27using System.Linq;
28using System.Text;
29using System.Windows.Forms;
30using HeuristicLab.MainForm;
31using HeuristicLab.Core;
32using HeuristicLab.Core.Views;
33using Netron.Diagramming.Core;
34using HeuristicLab.Parameters;
35using HeuristicLab.MainForm.WindowsForms;
36using HeuristicLab.Collections;
37
38namespace HeuristicLab.Operators.Views.GraphVisualization {
39
40  [Content(typeof(OperatorGraph), false)]
41  public partial class OperatorGraphView : ContentView {
42    private BidirectionalLookup<IShapeInfo, IShape> shapeInfoShapeMapping;
43    private BidirectionalLookup<IShapeInfo, INotifyObservableDictionaryItemsChanged<string, IShapeInfo>> shapeInfoConnectionsMapping;
44    private BidirectionalLookup<IConnection, KeyValuePair<IConnector, IConnector>> connectionConnectorsMapping;
45
46    private bool causedUpdateOfShapeInfo;
47    public OperatorGraphView() {
48      InitializeComponent();
49      this.causedUpdateOfShapeInfo = false;
50      Caption = "Operator Graph";
51      this.shapeInfoShapeMapping = new BidirectionalLookup<IShapeInfo, IShape>();
52      this.shapeInfoConnectionsMapping = new BidirectionalLookup<IShapeInfo, INotifyObservableDictionaryItemsChanged<string, IShapeInfo>>();
53      this.connectionConnectorsMapping = new BidirectionalLookup<IConnection, KeyValuePair<IConnector, IConnector>>();
54    }
55
56    public OperatorGraphView(OperatorGraph content)
57      : this() {
58      this.Content = content;
59    }
60
61    public new OperatorGraph Content {
62      get { return (OperatorGraph)base.Content; }
63      set { base.Content = value; }
64    }
65
66    protected override void OnContentChanged() {
67      if (this.VisualizationInfo == null)
68        this.VisualizationInfo = new OperatorGraphVisualizationInfo(this.Content);
69      this.UpdateVisualizationInfo();
70    }
71
72    private OperatorGraphVisualizationInfo VisualizationInfo {
73      get { return Content.VisualizationInfo as OperatorGraphVisualizationInfo; }
74      set { this.Content.VisualizationInfo = value; }
75    }
76
77    private void UpdateVisualizationInfo() {
78      foreach (IShapeInfo shapeInfo in this.shapeInfoShapeMapping.FirstValues)
79        this.RemoveShapeInfo(shapeInfo);
80
81      this.shapeInfoShapeMapping.Clear();
82      this.shapeInfoConnectionsMapping.Clear();
83      this.connectionConnectorsMapping.Clear();
84
85      foreach (IShapeInfo shapeInfo in this.VisualizationInfo.ShapeInfos)
86        if (!this.shapeInfoShapeMapping.ContainsFirst(shapeInfo))
87          this.AddShapeInfo(shapeInfo);
88
89      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> connection in this.VisualizationInfo.Connections)
90        this.AddConnection(connection.Key.Key, connection.Key.Value, connection.Value);
91
92      this.UpdateLayoutRoot();
93    }
94
95    private void UpdateLayoutRoot() {
96      IShapeInfo shapeInfo = this.VisualizationInfo.InitialShape;
97      if (shapeInfo != null)
98        this.graphVisualization.Controller.Model.LayoutRoot = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
99      else
100        this.graphVisualization.Controller.Model.LayoutRoot = null;
101    }
102
103    private void VisualizationInfo_InitialShapeChanged(object sender, EventArgs e) {
104      this.UpdateLayoutRoot();
105    }
106
107    protected override void RegisterContentEvents() {
108      base.RegisterContentEvents();
109      this.VisualizationInfo.InitialShapeChanged += new EventHandler(VisualizationInfo_InitialShapeChanged);
110      this.VisualizationInfo.ObserveableShapeInfos.ItemsAdded += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsAdded);
111      this.VisualizationInfo.ObserveableShapeInfos.ItemsRemoved += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsRemoved);
112      this.VisualizationInfo.ObserveableShapeInfos.CollectionReset += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_CollectionReset);
113
114      this.VisualizationInfo.ObservableConnections.ItemsAdded += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsAdded);
115      this.VisualizationInfo.ObservableConnections.ItemsRemoved += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsRemoved);
116      this.VisualizationInfo.ObservableConnections.ItemsReplaced += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsReplaced);
117      this.VisualizationInfo.ObservableConnections.CollectionReset += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_CollectionReset);
118    }
119
120    protected override void DeregisterContentEvents() {
121      base.DeregisterContentEvents();
122      this.VisualizationInfo.InitialShapeChanged -= new EventHandler(VisualizationInfo_InitialShapeChanged);
123      this.VisualizationInfo.ObserveableShapeInfos.ItemsAdded -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsAdded);
124      this.VisualizationInfo.ObserveableShapeInfos.ItemsRemoved -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsRemoved);
125      this.VisualizationInfo.ObserveableShapeInfos.CollectionReset -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_CollectionReset);
126
127      this.VisualizationInfo.ObservableConnections.ItemsAdded -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsAdded);
128      this.VisualizationInfo.ObservableConnections.ItemsRemoved -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsRemoved);
129      this.VisualizationInfo.ObservableConnections.ItemsReplaced -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsReplaced);
130      this.VisualizationInfo.ObservableConnections.CollectionReset -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_CollectionReset);
131    }
132
133    private void ShapeInfos_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
134      foreach (IShapeInfo shapeInfo in e.OldItems)
135        this.RemoveShapeInfo(shapeInfo);
136      foreach (IShapeInfo shapeInfo in e.Items)
137        this.AddShapeInfo(shapeInfo);
138    }
139
140    private void ShapeInfos_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
141      foreach (IShapeInfo shapeInfo in e.Items)
142        this.AddShapeInfo(shapeInfo);
143    }
144
145    private void ShapeInfos_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
146      foreach (IShapeInfo shapeInfo in e.Items)
147        this.RemoveShapeInfo(shapeInfo);
148    }
149
150    private void AddShapeInfo(IShapeInfo shapeInfo) {
151      this.RegisterShapeInfoEvents(shapeInfo);
152
153      IShape shape = shapeInfo.CreateShape();
154      shape.OnEntityChange += new EventHandler<EntityEventArgs>(shape_OnEntityChange);
155      this.shapeInfoShapeMapping.Add(shapeInfo, shape);
156
157      this.graphVisualization.Controller.Model.AddShape(shape);
158    }
159
160    private void RemoveShapeInfo(IShapeInfo shapeInfo) {
161      this.DeregisterShapeInfoEvents(shapeInfo);
162      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
163      shape.OnEntityChange -= new EventHandler<EntityEventArgs>(shape_OnEntityChange);
164      shapeInfo.Changed -= new ChangedEventHandler(shapeInfo_Changed);
165
166      IConnection connection;
167      foreach (IConnector connector in shape.Connectors) {
168        connection = this.GetConnection(shapeInfo, connector.Name);
169        this.RemoveConnection(connection);
170      }
171
172      this.shapeInfoShapeMapping.RemoveByFirst(shapeInfo);
173      this.shapeInfoConnectionsMapping.RemoveByFirst(shapeInfo);
174
175      if (this.graphVisualization.Controller.Model.Shapes.Contains(shape)) {
176        this.graphVisualization.Controller.Model.RemoveShape(shape);
177      }
178    }
179
180    private void RegisterShapeInfoEvents(IShapeInfo shapeInfo) {
181      shapeInfo.Changed += new ChangedEventHandler(shapeInfo_Changed);
182    }
183
184    private void DeregisterShapeInfoEvents(IShapeInfo shapeInfo) {
185      shapeInfo.Changed -= new ChangedEventHandler(shapeInfo_Changed);
186    }
187
188    private void Connections_CollectionReset(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>> e) {
189      IConnection connection;
190      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items) {
191        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
192        this.RemoveConnection(connection);
193      }
194      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items)
195        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
196    }
197
198    private void Connections_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>> e) {
199      IConnection connection;
200      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items) {
201        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
202        this.RemoveConnection(connection);
203      }
204      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items)
205        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
206    }
207
208    private void Connections_ItemsAdded(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>> e) {
209      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items)
210        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
211    }
212
213    private void Connections_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>> e) {
214      IConnection connection;
215      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items) {
216        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
217        this.RemoveConnection(connection);
218      }
219    }
220
221    private void AddConnection(IShapeInfo shapeInfoFrom, string connectorName, IShapeInfo shapeInfoTo) {
222      IShape shapeFrom = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
223      IShape shapeTo = this.shapeInfoShapeMapping.GetByFirst(shapeInfoTo);
224
225      IConnector connectorFrom = shapeFrom.Connectors.Where(c => c.Name == connectorName).First();
226      IConnector connectorTo = shapeTo.Connectors.Where(c => c.Name == "Predecessor").FirstOrDefault();
227      KeyValuePair<IConnector, IConnector> connectorPair = new KeyValuePair<IConnector, IConnector>(connectorFrom, connectorTo);
228      if (!this.connectionConnectorsMapping.ContainsSecond(connectorPair)) {
229        IConnection connection = Factory.CreateConnection(connectorFrom, connectorTo);
230        this.connectionConnectorsMapping.Add(connection, connectorPair);
231        this.graphVisualization.Controller.Model.AddConnection(connection);
232        this.graphVisualization.Invalidate();
233      }
234    }
235
236    private IConnection GetConnection(IShapeInfo shapeInfoFrom, string connectorName) {
237      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
238      IConnector connector = shape.Connectors.Where(c => c.Name == connectorName).First();
239
240      if (!this.connectionConnectorsMapping.SecondValues.Any(p => p.Key == connector))
241        return null;
242
243      KeyValuePair<IConnector, IConnector> connectorPair = this.connectionConnectorsMapping.SecondValues.Where(p => p.Key == connector).FirstOrDefault();
244      return this.connectionConnectorsMapping.GetBySecond(connectorPair);
245    }
246
247    private void ChangeConnection(IShapeInfo shapeInfoFrom, string connectorName, IShapeInfo shapeInfoTo) {
248      IConnection connection = this.GetConnection(shapeInfoFrom, connectorName);
249      IShape shapeTo = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
250      IConnector connectorTo = shapeTo.Connectors.Where(c => c.Name == "Predecessor").First();
251
252      connection.To.DetachFromParent();
253      connection.To.AttachTo(connectorTo);
254      this.graphVisualization.Invalidate();
255    }
256
257    private void RemoveConnection(IConnection connection) {
258      if (connection == null)
259        return;
260
261      if (connection.From.AttachedTo != null)
262        connection.From.DetachFromParent();
263      if (connection.To.AttachedTo != null)
264        connection.To.DetachFromParent();
265
266      if (this.connectionConnectorsMapping.ContainsFirst(connection))
267        this.connectionConnectorsMapping.RemoveByFirst(connection);
268      if (this.graphVisualization.Controller.Model.Connections.Contains(connection))
269        this.graphVisualization.Controller.Model.Remove(connection);
270      this.graphVisualization.Invalidate();
271    }
272
273
274    private void shapeInfo_Changed(object sender, ChangedEventArgs e) {
275      if (this.causedUpdateOfShapeInfo)
276        return;
277
278      IShapeInfo shapeInfo = (IShapeInfo)sender;
279      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
280      shapeInfo.UpdateShape(shape);
281    }
282
283
284    private void shape_OnEntityChange(object sender, EntityEventArgs e) {
285      this.causedUpdateOfShapeInfo = true;
286      IShape shape = e.Entity as IShape;
287      IShapeInfo shapeInfo = this.shapeInfoShapeMapping.GetBySecond(shape);
288
289      shapeInfo.Location = shape.Location;
290      shapeInfo.Size = new Size(shape.Width, shape.Height);
291
292      this.graphVisualization.Invalidate();
293      this.causedUpdateOfShapeInfo = false;
294    }
295
296    private void graphVisualization_OnEntityAdded(object sender, EntityEventArgs e) {
297      IConnection connection = e.Entity as IConnection;
298      if (connection != null && !this.connectionConnectorsMapping.ContainsFirst(connection)) {
299        IConnector connectorFrom = connection.From.AttachedTo;
300        IConnector connectorTo = connection.To.AttachedTo;
301        this.RemoveConnection(connection); //is added again by the model events
302
303        if (connectorFrom != null && connectorTo != null) {
304          IShape shapeFrom = (IShape)connectorFrom.Parent;
305          IShape shapeTo = (IShape)connectorTo.Parent;
306          IShapeInfo shapeInfoFrom = this.shapeInfoShapeMapping.GetBySecond(shapeFrom);
307          IShapeInfo shapeInfoTo = this.shapeInfoShapeMapping.GetBySecond(shapeTo);
308          string connectorName = connectorFrom.Name;
309
310          this.VisualizationInfo.AddConnection(shapeInfoFrom, connectorName, shapeInfoTo);
311        }
312      }
313    }
314
315    private void graphVisualization_OnEntityRemoved(object sender, EntityEventArgs e) {
316      IShape shape = e.Entity as IShape;
317      if (shape != null && this.shapeInfoShapeMapping.ContainsSecond(shape)) {
318        IShapeInfo shapeInfo = this.shapeInfoShapeMapping.GetBySecond(shape);
319        this.VisualizationInfo.RemoveShapeInfo(shapeInfo);
320      }
321
322      IConnection connection = e.Entity as IConnection;
323      if (connection != null && this.connectionConnectorsMapping.ContainsFirst(connection)) {
324        IShape parentShape = (IShape)connection.From.AttachedTo.Parent;
325        IShapeInfo shapeInfo = this.shapeInfoShapeMapping.GetBySecond(parentShape);
326        string connectorName = connection.From.AttachedTo.Name;
327
328        this.VisualizationInfo.RemoveConnection(shapeInfo, connectorName);
329      }
330    }
331
332    #region methods for toolbar items
333
334    private int layoutCount = 0;
335    internal void RelayoutOperatorGraph() {
336      if (this.shapeInfoShapeMapping.Count > 0 && this.connectionConnectorsMapping.Count > 0) { //otherwise the layout does not work
337
338        string layoutName = string.Empty;
339        switch (this.layoutCount % 6) {
340          case 0: { layoutName = "Random Layout"; break; }
341          case 1: { layoutName = "FruchtermanReingold Layout"; break; }
342          case 2: { layoutName = "Standard TreeLayout"; break; }
343          case 3: { layoutName = "Radial TreeLayout"; break; }
344          case 4: { layoutName = "Balloon TreeLayout"; break; }
345          case 5: { layoutName = "ForceDirected Layout"; break; }
346        }
347        this.graphVisualization.Controller.RunActivity(layoutName);
348        MessageBox.Show(layoutName);
349        this.layoutCount++;
350        this.graphVisualization.Invalidate();
351      }
352    }
353
354    internal void ActivateConnectionTool() {
355      this.graphVisualization.Controller.ActivateTool(ControllerBase.ConnectionToolName);
356    }
357
358    internal void ActivateZoomAreaTool() {
359      this.graphVisualization.Controller.ActivateTool(ControllerBase.ZoomAreaToolName);
360    }
361
362    internal void ActivateZoomInTool() {
363      this.graphVisualization.Controller.ActivateTool(ControllerBase.ZoomInToolName);
364    }
365
366    internal void ActivateZoomOutTool() {
367      this.graphVisualization.Controller.ActivateTool(ControllerBase.ZoomOutToolName);
368    }
369
370    internal void ActivatePanTool() {
371      this.graphVisualization.Controller.ActivateTool(ControllerBase.PanToolName);
372    }
373
374    internal void ActivateSelectTool() {
375      this.graphVisualization.Controller.ActivateTool(ControllerBase.SelectionToolName);
376    }
377
378    #endregion
379
380    #region drag and drop
381    private void OperatorGraphView_DragEnter(object sender, DragEventArgs e) {
382      e.Effect = DragDropEffects.None;
383      Type type = e.Data.GetData("Type") as Type;
384      if ((type != null) && (typeof(IOperator).IsAssignableFrom(type))) {
385        e.Effect = DragDropEffects.Copy;
386      }
387    }
388
389    private void OperatorGraphView_DragDrop(object sender, DragEventArgs e) {
390      if (e.Effect != DragDropEffects.None) {
391        IOperator op = e.Data.GetData("Value") as IOperator;
392        IShapeInfo shapeInfo = Factory.CreateShapeInfo(op);
393        Point controlCoordinates = this.PointToClient(new Point(e.X, e.Y));
394        PointF viewCoordinates = this.graphVisualization.Controller.View.DeviceToView(controlCoordinates);
395        shapeInfo.Location = new Point((int)viewCoordinates.X, (int)viewCoordinates.Y);
396        this.VisualizationInfo.AddShapeInfo(op, shapeInfo);
397      }
398    }
399
400    #endregion
401  }
402}
Note: See TracBrowser for help on using the repository browser.