Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/GraphVisualizationInfoView.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: 19.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Common;
32using HeuristicLab.Core;
33using HeuristicLab.Core.Views;
34using Netron.Diagramming.Core;
35using HeuristicLab.Parameters;
36using HeuristicLab.MainForm.WindowsForms;
37using HeuristicLab.Collections;
38using System.Diagnostics;
39using System.Threading;
40
41namespace HeuristicLab.Operators.Views.GraphVisualization {
42  [View("GraphVisualizationInfo View")]
43  [Content(typeof(GraphVisualizationInfo), false)]
44  public partial class GraphVisualizationInfoView : ContentView {
45    private BidirectionalLookup<IOperatorShapeInfo, IShape> shapeInfoShapeMapping;
46    private BidirectionalLookup<IOperatorShapeInfo, INotifyObservableDictionaryItemsChanged<string, IOperatorShapeInfo>> shapeInfoConnectionsMapping;
47    private BidirectionalLookup<IConnection, KeyValuePair<IConnector, IConnector>> connectionConnectorsMapping;
48
49    private bool causedUpdateOfShapeInfo;
50    public GraphVisualizationInfoView() {
51      InitializeComponent();
52      this.causedUpdateOfShapeInfo = false;
53      this.shapeInfoShapeMapping = new BidirectionalLookup<IOperatorShapeInfo, IShape>();
54      this.shapeInfoConnectionsMapping = new BidirectionalLookup<IOperatorShapeInfo, INotifyObservableDictionaryItemsChanged<string, IOperatorShapeInfo>>();
55      this.connectionConnectorsMapping = new BidirectionalLookup<IConnection, KeyValuePair<IConnector, IConnector>>();
56    }
57
58    public GraphVisualizationInfoView(GraphVisualizationInfo content)
59      : this() {
60      this.Content = content;
61    }
62
63    public IController Controller {
64      get { return this.graphVisualization.Controller; }
65    }
66
67    public new GraphVisualizationInfo Content {
68      get { return (GraphVisualizationInfo)base.Content; }
69      set { base.Content = value; }
70    }
71
72    protected override void OnContentChanged() {
73      base.OnContentChanged();
74      this.UpdateContent();
75    }
76
77    protected override void OnReadOnlyChanged() {
78      base.OnReadOnlyChanged();
79      this.SetEnabledStateOfControls();
80    }
81
82    private void SetEnabledStateOfControls() {
83      DeleteTool deleteTool = (DeleteTool) this.Controller.Tools.Where( t => t.Name == ControllerBase.DeleteToolName).FirstOrDefault();
84      HeuristicLab.Netron.Controller controller = this.Controller as HeuristicLab.Netron.Controller;
85      if (Content == null && deleteTool != null && controller != null)
86        controller.RemoveTool(deleteTool);
87      else {
88        if (ReadOnly && deleteTool != null && controller != null)
89          controller.RemoveTool(deleteTool);
90        else if (!ReadOnly && deleteTool == null)
91          this.Controller.AddTool(new DeleteTool(ControllerBase.DeleteToolName));
92      }
93    }
94
95    private void UpdateContent() {
96      foreach (IOperatorShapeInfo shapeInfo in this.shapeInfoShapeMapping.FirstValues)
97        this.RemoveShapeInfo(shapeInfo);
98
99      this.shapeInfoShapeMapping.Clear();
100      this.shapeInfoConnectionsMapping.Clear();
101      this.connectionConnectorsMapping.Clear();
102
103      if (Content != null) {
104        foreach (IOperatorShapeInfo shapeInfo in this.Content.OperatorShapeInfos)
105          if (!this.shapeInfoShapeMapping.ContainsFirst(shapeInfo))
106            this.AddShapeInfo(shapeInfo);
107
108        foreach (KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo> connection in this.Content.Connections)
109          this.AddConnection(connection.Key.Key, connection.Key.Value, connection.Value);
110
111        this.UpdateLayoutRoot();
112      }
113      this.SetEnabledStateOfControls();
114    }
115
116    private void UpdateLayoutRoot() {
117      IOperatorShapeInfo shapeInfo = this.Content.InitialShape;
118      if (shapeInfo != null)
119        this.graphVisualization.Controller.Model.LayoutRoot = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
120      else
121        this.graphVisualization.Controller.Model.LayoutRoot = null;
122    }
123
124    private void VisualizationInfo_InitialShapeChanged(object sender, EventArgs e) {
125      this.UpdateLayoutRoot();
126    }
127
128    protected override void RegisterContentEvents() {
129      base.RegisterContentEvents();
130      this.Content.InitialShapeChanged += new EventHandler(VisualizationInfo_InitialShapeChanged);
131      this.Content.ObserveableShapeInfos.ItemsAdded += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperatorShapeInfo>(ShapeInfos_ItemsAdded);
132      this.Content.ObserveableShapeInfos.ItemsRemoved += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperatorShapeInfo>(ShapeInfos_ItemsRemoved);
133      this.Content.ObserveableShapeInfos.CollectionReset += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperatorShapeInfo>(ShapeInfos_CollectionReset);
134
135      this.Content.ObservableConnections.ItemsAdded += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>>(Connections_ItemsAdded);
136      this.Content.ObservableConnections.ItemsRemoved += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>>(Connections_ItemsRemoved);
137      this.Content.ObservableConnections.ItemsReplaced += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>>(Connections_ItemsReplaced);
138      this.Content.ObservableConnections.CollectionReset += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>>(Connections_CollectionReset);
139    }
140
141    protected override void DeregisterContentEvents() {
142      base.DeregisterContentEvents();
143      this.Content.InitialShapeChanged -= new EventHandler(VisualizationInfo_InitialShapeChanged);
144      this.Content.ObserveableShapeInfos.ItemsAdded -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperatorShapeInfo>(ShapeInfos_ItemsAdded);
145      this.Content.ObserveableShapeInfos.ItemsRemoved -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperatorShapeInfo>(ShapeInfos_ItemsRemoved);
146      this.Content.ObserveableShapeInfos.CollectionReset -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IOperatorShapeInfo>(ShapeInfos_CollectionReset);
147
148      this.Content.ObservableConnections.ItemsAdded -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>>(Connections_ItemsAdded);
149      this.Content.ObservableConnections.ItemsRemoved -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>>(Connections_ItemsRemoved);
150      this.Content.ObservableConnections.ItemsReplaced -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>>(Connections_ItemsReplaced);
151      this.Content.ObservableConnections.CollectionReset -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>>(Connections_CollectionReset);
152    }
153
154    private void ShapeInfos_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperatorShapeInfo> e) {
155      foreach (IOperatorShapeInfo shapeInfo in e.OldItems)
156        this.RemoveShapeInfo(shapeInfo);
157      foreach (IOperatorShapeInfo shapeInfo in e.Items)
158        this.AddShapeInfo(shapeInfo);
159    }
160
161    private void ShapeInfos_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperatorShapeInfo> e) {
162      foreach (IOperatorShapeInfo shapeInfo in e.Items)
163        this.AddShapeInfo(shapeInfo);
164    }
165
166    private void ShapeInfos_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IOperatorShapeInfo> e) {
167      foreach (IOperatorShapeInfo shapeInfo in e.Items)
168        this.RemoveShapeInfo(shapeInfo);
169    }
170
171    private void AddShapeInfo(IOperatorShapeInfo shapeInfo) {
172      this.RegisterShapeInfoEvents(shapeInfo);
173
174      IShape shape = shapeInfo.CreateShape();
175      shape.OnEntityChange += new EventHandler<EntityEventArgs>(shape_OnEntityChange);
176      shape.OnMouseEnter += new EventHandler<EntityMouseEventArgs>(shape_OnMouseEnter);
177      shape.OnMouseLeave += new EventHandler<EntityMouseEventArgs>(shape_OnMouseLeave);
178      this.shapeInfoShapeMapping.Add(shapeInfo, shape);
179
180      this.graphVisualization.Controller.Model.AddShape(shape);
181      this.graphVisualization.Invalidate();
182    }
183
184    private void RemoveShapeInfo(IOperatorShapeInfo shapeInfo) {
185      this.DeregisterShapeInfoEvents(shapeInfo);
186      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
187      shape.OnEntityChange -= new EventHandler<EntityEventArgs>(shape_OnEntityChange);
188      shape.OnMouseEnter -= new EventHandler<EntityMouseEventArgs>(shape_OnMouseEnter);
189      shape.OnMouseLeave -= new EventHandler<EntityMouseEventArgs>(shape_OnMouseLeave);
190
191      IConnection connection;
192      foreach (IConnector connector in shape.Connectors) {
193        connection = this.GetConnection(shapeInfo, connector.Name);
194        this.RemoveConnection(connection);
195      }
196
197      this.shapeInfoShapeMapping.RemoveByFirst(shapeInfo);
198      this.shapeInfoConnectionsMapping.RemoveByFirst(shapeInfo);
199
200      if (this.graphVisualization.Controller.Model.Shapes.Contains(shape)) {
201        this.graphVisualization.Controller.Model.RemoveShape(shape);
202      }
203      this.graphVisualization.Invalidate();
204    }
205
206    private void RegisterShapeInfoEvents(IShapeInfo shapeInfo) {
207      shapeInfo.Changed += new EventHandler(shapeInfo_Changed);
208    }
209
210    private void DeregisterShapeInfoEvents(IShapeInfo shapeInfo) {
211      shapeInfo.Changed -= new EventHandler(shapeInfo_Changed);
212    }
213
214    private void Connections_CollectionReset(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>> e) {
215      IConnection connection;
216      foreach (KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo> pair in e.Items) {
217        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
218        this.RemoveConnection(connection);
219      }
220      foreach (KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo> pair in e.Items)
221        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
222    }
223
224    private void Connections_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>> e) {
225      IConnection connection;
226      foreach (KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo> pair in e.Items) {
227        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
228        this.RemoveConnection(connection);
229      }
230      foreach (KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo> pair in e.Items)
231        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
232    }
233
234    private void Connections_ItemsAdded(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>> e) {
235      foreach (KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo> pair in e.Items)
236        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
237    }
238
239    private void Connections_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo>> e) {
240      IConnection connection;
241      foreach (KeyValuePair<KeyValuePair<IOperatorShapeInfo, string>, IOperatorShapeInfo> pair in e.Items) {
242        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
243        this.RemoveConnection(connection);
244      }
245    }
246
247    private void AddConnection(IOperatorShapeInfo shapeInfoFrom, string connectorName, IOperatorShapeInfo shapeInfoTo) {
248      IShape shapeFrom = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
249      IShape shapeTo = this.shapeInfoShapeMapping.GetByFirst(shapeInfoTo);
250
251      IConnector connectorFrom = shapeFrom.Connectors.Where(c => c.Name == connectorName).First();
252      IConnector connectorTo = shapeTo.Connectors.Where(c => c.Name == "Predecessor").FirstOrDefault();
253      KeyValuePair<IConnector, IConnector> connectorPair = new KeyValuePair<IConnector, IConnector>(connectorFrom, connectorTo);
254      if (!this.connectionConnectorsMapping.ContainsSecond(connectorPair)) {
255        IConnection connection = Factory.CreateConnection(connectorFrom, connectorTo);
256        this.connectionConnectorsMapping.Add(connection, connectorPair);
257        this.graphVisualization.Controller.Model.AddConnection(connection);
258        this.graphVisualization.Invalidate();
259      }
260    }
261
262    private IConnection GetConnection(IOperatorShapeInfo shapeInfoFrom, string connectorName) {
263      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
264      IConnector connector = shape.Connectors.Where(c => c.Name == connectorName).First();
265
266      if (!this.connectionConnectorsMapping.SecondValues.Any(p => p.Key == connector))
267        return null;
268
269      KeyValuePair<IConnector, IConnector> connectorPair = this.connectionConnectorsMapping.SecondValues.Where(p => p.Key == connector).FirstOrDefault();
270      return this.connectionConnectorsMapping.GetBySecond(connectorPair);
271    }
272
273    private void ChangeConnection(IOperatorShapeInfo shapeInfoFrom, string connectorName, IOperatorShapeInfo shapeInfoTo) {
274      IConnection connection = this.GetConnection(shapeInfoFrom, connectorName);
275      IShape shapeTo = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
276      IConnector connectorTo = shapeTo.Connectors.Where(c => c.Name == "Predecessor").First();
277
278      connection.To.DetachFromParent();
279      connection.To.AttachTo(connectorTo);
280      this.graphVisualization.Invalidate();
281    }
282
283    private void RemoveConnection(IConnection connection) {
284      if (connection == null)
285        return;
286
287      if (connection.From.AttachedTo != null)
288        connection.From.DetachFromParent();
289      if (connection.To.AttachedTo != null)
290        connection.To.DetachFromParent();
291
292      if (this.connectionConnectorsMapping.ContainsFirst(connection))
293        this.connectionConnectorsMapping.RemoveByFirst(connection);
294      if (this.graphVisualization.Controller.Model.Connections.Contains(connection))
295        this.graphVisualization.Controller.Model.Remove(connection);
296      this.graphVisualization.Invalidate();
297    }
298
299
300    private void shapeInfo_Changed(object sender, EventArgs e) {
301      if (this.causedUpdateOfShapeInfo)
302        return;
303
304      this.causedUpdateOfShapeInfo = true;
305      IOperatorShapeInfo shapeInfo = (IOperatorShapeInfo)sender;
306      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
307      shapeInfo.UpdateShape(shape);
308      shape.Invalidate();
309      this.causedUpdateOfShapeInfo = false;
310    }
311
312    private Cursor oldCursor;
313    private void shape_OnMouseEnter(object sender, EntityMouseEventArgs e) {
314      this.oldCursor = this.Cursor;
315      this.Controller.View.CurrentCursor = CursorPalette.Move;
316    }
317
318    private void shape_OnMouseLeave(object sender, EntityMouseEventArgs e) {
319      this.Controller.View.CurrentCursor = this.oldCursor;
320      this.oldCursor = null;
321    }
322
323    private void shape_OnEntityChange(object sender, EntityEventArgs e) {
324      if (this.causedUpdateOfShapeInfo)
325        return;
326
327      this.causedUpdateOfShapeInfo = true;
328      IShape shape = e.Entity as IShape;
329      IOperatorShapeInfo shapeInfo = this.shapeInfoShapeMapping.GetBySecond(shape);
330      shapeInfo.Location = shape.Location;
331
332      OperatorShape operatorShape = shape as OperatorShape;
333      if (operatorShape != null)
334        shapeInfo.Collapsed = operatorShape.Collapsed;
335
336      this.graphVisualization.Invalidate();
337      this.causedUpdateOfShapeInfo = false;
338    }
339
340    private void graphVisualization_OnEntityAdded(object sender, EntityEventArgs e) {
341      IConnection connection = e.Entity as IConnection;
342      if (connection != null && !this.connectionConnectorsMapping.ContainsFirst(connection)) {
343        IConnector connectorFrom = connection.From.AttachedTo;
344        IConnector connectorTo = connection.To.AttachedTo;
345        this.RemoveConnection(connection); //is added again by the model events
346
347        if (connectorFrom != null && connectorTo != null && connectorFrom.Name != "Predecessor") {
348          IShape shapeFrom = (IShape)connectorFrom.Parent;
349          IShape shapeTo = (IShape)connectorTo.Parent;
350          IOperatorShapeInfo shapeInfoFrom = this.shapeInfoShapeMapping.GetBySecond(shapeFrom);
351          IOperatorShapeInfo shapeInfoTo = this.shapeInfoShapeMapping.GetBySecond(shapeTo);
352          string connectorName = connectorFrom.Name;
353
354          if (shapeFrom != shapeTo) //avoid self references
355            this.Content.AddConnection(shapeInfoFrom, connectorName, shapeInfoTo);
356        }
357      }
358    }
359
360    private void graphVisualization_OnEntityRemoved(object sender, EntityEventArgs e) {
361      IShape shape = e.Entity as IShape;
362      if (shape != null && this.shapeInfoShapeMapping.ContainsSecond(shape)) {
363        IOperatorShapeInfo shapeInfo = this.shapeInfoShapeMapping.GetBySecond(shape);
364        this.Content.RemoveShapeInfo(shapeInfo);
365      }
366
367      IConnection connection = e.Entity as IConnection;
368      if (connection != null && this.connectionConnectorsMapping.ContainsFirst(connection)) {
369        IShape parentShape = (IShape)connection.From.AttachedTo.Parent;
370        IOperatorShapeInfo shapeInfo = this.shapeInfoShapeMapping.GetBySecond(parentShape);
371        string connectorName = connection.From.AttachedTo.Name;
372
373        this.Content.RemoveConnection(shapeInfo, connectorName);
374      }
375    }
376
377    internal void RelayoutGraph() {
378      if (this.shapeInfoShapeMapping.Count > 0
379        && this.connectionConnectorsMapping.Count > 0
380        && this.Content.InitialShape != null) { //otherwise the layout does not work
381        string layoutName = "Standard TreeLayout";
382        this.graphVisualization.Controller.RunActivity(layoutName);
383        this.graphVisualization.Invalidate();
384
385        //fix to avoid negative shape positions after layouting
386        Thread.Sleep(300);
387        int minX = this.graphVisualization.Controller.Model.Shapes.Min(s => s.Location.X);
388        int shiftX = minX < 0 ? Math.Abs(minX) + 50 : 0;
389        int minY = this.graphVisualization.Controller.Model.Shapes.Min(s => s.Location.Y);
390        int shiftY = minY < 0 ? Math.Abs(minY) + 50 : 0;
391        if (minX < 0 || minY < 0) {
392          foreach (IShape s in this.Controller.Model.Shapes)
393            s.MoveBy(new Point(shiftX, shiftY));
394        }
395      }
396    }
397  }
398}
Note: See TracBrowser for help on using the repository browser.