Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Operators.Views.GraphVisualization/3.3/GraphVisualizationInfoView.cs @ 2910

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

added tooltips for graph visualization buttons and fixed layouting problems (ticket #867)

File size: 17.0 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.Core;
32using HeuristicLab.Core.Views;
33using Netron.Diagramming.Core;
34using HeuristicLab.Parameters;
35using HeuristicLab.MainForm.WindowsForms;
36using HeuristicLab.Collections;
37using System.Diagnostics;
38using System.Threading;
39
40namespace HeuristicLab.Operators.Views.GraphVisualization {
41  [Content(typeof(GraphVisualizationInfo), false)]
42  public partial class GraphVisualizationInfoView : ContentView {
43    private BidirectionalLookup<IShapeInfo, IShape> shapeInfoShapeMapping;
44    private BidirectionalLookup<IShapeInfo, INotifyObservableDictionaryItemsChanged<string, IShapeInfo>> shapeInfoConnectionsMapping;
45    private BidirectionalLookup<IConnection, KeyValuePair<IConnector, IConnector>> connectionConnectorsMapping;
46
47    private bool causedUpdateOfShapeInfo;
48    public GraphVisualizationInfoView() {
49      InitializeComponent();
50      this.causedUpdateOfShapeInfo = false;
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 GraphVisualizationInfoView(GraphVisualizationInfo content)
57      : this() {
58      this.Content = content;
59    }
60
61    public IController Controller {
62      get { return this.graphVisualization.Controller; }
63    }
64
65    public new GraphVisualizationInfo Content {
66      get { return (GraphVisualizationInfo)base.Content; }
67      set { base.Content = value; }
68    }
69
70    protected override void OnContentChanged() {
71      base.OnContentChanged();
72      this.UpdateContent();
73    }
74
75    private void UpdateContent() {
76      foreach (IShapeInfo shapeInfo in this.shapeInfoShapeMapping.FirstValues)
77        this.RemoveShapeInfo(shapeInfo);
78
79      this.shapeInfoShapeMapping.Clear();
80      this.shapeInfoConnectionsMapping.Clear();
81      this.connectionConnectorsMapping.Clear();
82
83      foreach (IShapeInfo shapeInfo in this.Content.ShapeInfos)
84        if (!this.shapeInfoShapeMapping.ContainsFirst(shapeInfo))
85          this.AddShapeInfo(shapeInfo);
86
87      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> connection in this.Content.Connections)
88        this.AddConnection(connection.Key.Key, connection.Key.Value, connection.Value);
89
90      this.UpdateLayoutRoot();
91    }
92
93    private void UpdateLayoutRoot() {
94      IShapeInfo shapeInfo = this.Content.InitialShape;
95      if (shapeInfo != null)
96        this.graphVisualization.Controller.Model.LayoutRoot = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
97      else
98        this.graphVisualization.Controller.Model.LayoutRoot = null;
99    }
100
101    private void VisualizationInfo_InitialShapeChanged(object sender, EventArgs e) {
102      this.UpdateLayoutRoot();
103    }
104
105    protected override void RegisterContentEvents() {
106      base.RegisterContentEvents();
107      this.Content.InitialShapeChanged += new EventHandler(VisualizationInfo_InitialShapeChanged);
108      this.Content.ObserveableShapeInfos.ItemsAdded += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsAdded);
109      this.Content.ObserveableShapeInfos.ItemsRemoved += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsRemoved);
110      this.Content.ObserveableShapeInfos.CollectionReset += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_CollectionReset);
111
112      this.Content.ObservableConnections.ItemsAdded += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsAdded);
113      this.Content.ObservableConnections.ItemsRemoved += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsRemoved);
114      this.Content.ObservableConnections.ItemsReplaced += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsReplaced);
115      this.Content.ObservableConnections.CollectionReset += new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_CollectionReset);
116    }
117
118    protected override void DeregisterContentEvents() {
119      base.DeregisterContentEvents();
120      this.Content.InitialShapeChanged -= new EventHandler(VisualizationInfo_InitialShapeChanged);
121      this.Content.ObserveableShapeInfos.ItemsAdded -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsAdded);
122      this.Content.ObserveableShapeInfos.ItemsRemoved -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsRemoved);
123      this.Content.ObserveableShapeInfos.CollectionReset -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_CollectionReset);
124
125      this.Content.ObservableConnections.ItemsAdded -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsAdded);
126      this.Content.ObservableConnections.ItemsRemoved -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsRemoved);
127      this.Content.ObservableConnections.ItemsReplaced -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_ItemsReplaced);
128      this.Content.ObservableConnections.CollectionReset -= new CollectionItemsChangedEventHandler<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>>(Connections_CollectionReset);
129    }
130
131    private void ShapeInfos_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
132      foreach (IShapeInfo shapeInfo in e.OldItems)
133        this.RemoveShapeInfo(shapeInfo);
134      foreach (IShapeInfo shapeInfo in e.Items)
135        this.AddShapeInfo(shapeInfo);
136    }
137
138    private void ShapeInfos_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
139      foreach (IShapeInfo shapeInfo in e.Items)
140        this.AddShapeInfo(shapeInfo);
141    }
142
143    private void ShapeInfos_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
144      foreach (IShapeInfo shapeInfo in e.Items)
145        this.RemoveShapeInfo(shapeInfo);
146    }
147
148    private void AddShapeInfo(IShapeInfo shapeInfo) {
149      this.RegisterShapeInfoEvents(shapeInfo);
150
151      IShape shape = shapeInfo.CreateShape();
152      shape.OnEntityChange += new EventHandler<EntityEventArgs>(shape_OnEntityChange);
153      this.shapeInfoShapeMapping.Add(shapeInfo, shape);
154
155      this.graphVisualization.Controller.Model.AddShape(shape);
156      this.graphVisualization.Invalidate();
157    }
158
159    private void RemoveShapeInfo(IShapeInfo shapeInfo) {
160      this.DeregisterShapeInfoEvents(shapeInfo);
161      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
162      shape.OnEntityChange -= new EventHandler<EntityEventArgs>(shape_OnEntityChange);
163
164      IConnection connection;
165      foreach (IConnector connector in shape.Connectors) {
166        connection = this.GetConnection(shapeInfo, connector.Name);
167        this.RemoveConnection(connection);
168      }
169
170      this.shapeInfoShapeMapping.RemoveByFirst(shapeInfo);
171      this.shapeInfoConnectionsMapping.RemoveByFirst(shapeInfo);
172
173      if (this.graphVisualization.Controller.Model.Shapes.Contains(shape)) {
174        this.graphVisualization.Controller.Model.RemoveShape(shape);
175      }
176      this.graphVisualization.Invalidate();
177    }
178
179    private void RegisterShapeInfoEvents(IShapeInfo shapeInfo) {
180      shapeInfo.Changed += new ChangedEventHandler(shapeInfo_Changed);
181    }
182
183    private void DeregisterShapeInfoEvents(IShapeInfo shapeInfo) {
184      shapeInfo.Changed -= new ChangedEventHandler(shapeInfo_Changed);
185    }
186
187    private void Connections_CollectionReset(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>> e) {
188      IConnection connection;
189      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items) {
190        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
191        this.RemoveConnection(connection);
192      }
193      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items)
194        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
195    }
196
197    private void Connections_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>> e) {
198      IConnection connection;
199      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items) {
200        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
201        this.RemoveConnection(connection);
202      }
203      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items)
204        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
205    }
206
207    private void Connections_ItemsAdded(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>> e) {
208      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items)
209        this.AddConnection(pair.Key.Key, pair.Key.Value, pair.Value);
210    }
211
212    private void Connections_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo>> e) {
213      IConnection connection;
214      foreach (KeyValuePair<KeyValuePair<IShapeInfo, string>, IShapeInfo> pair in e.Items) {
215        connection = this.GetConnection(pair.Key.Key, pair.Key.Value);
216        this.RemoveConnection(connection);
217      }
218    }
219
220    private void AddConnection(IShapeInfo shapeInfoFrom, string connectorName, IShapeInfo shapeInfoTo) {
221      IShape shapeFrom = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
222      IShape shapeTo = this.shapeInfoShapeMapping.GetByFirst(shapeInfoTo);
223
224      IConnector connectorFrom = shapeFrom.Connectors.Where(c => c.Name == connectorName).First();
225      IConnector connectorTo = shapeTo.Connectors.Where(c => c.Name == "Predecessor").FirstOrDefault();
226      KeyValuePair<IConnector, IConnector> connectorPair = new KeyValuePair<IConnector, IConnector>(connectorFrom, connectorTo);
227      if (!this.connectionConnectorsMapping.ContainsSecond(connectorPair)) {
228        IConnection connection = Factory.CreateConnection(connectorFrom, connectorTo);
229        this.connectionConnectorsMapping.Add(connection, connectorPair);
230        this.graphVisualization.Controller.Model.AddConnection(connection);
231        this.graphVisualization.Invalidate();
232      }
233    }
234
235    private IConnection GetConnection(IShapeInfo shapeInfoFrom, string connectorName) {
236      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
237      IConnector connector = shape.Connectors.Where(c => c.Name == connectorName).First();
238
239      if (!this.connectionConnectorsMapping.SecondValues.Any(p => p.Key == connector))
240        return null;
241
242      KeyValuePair<IConnector, IConnector> connectorPair = this.connectionConnectorsMapping.SecondValues.Where(p => p.Key == connector).FirstOrDefault();
243      return this.connectionConnectorsMapping.GetBySecond(connectorPair);
244    }
245
246    private void ChangeConnection(IShapeInfo shapeInfoFrom, string connectorName, IShapeInfo shapeInfoTo) {
247      IConnection connection = this.GetConnection(shapeInfoFrom, connectorName);
248      IShape shapeTo = this.shapeInfoShapeMapping.GetByFirst(shapeInfoFrom);
249      IConnector connectorTo = shapeTo.Connectors.Where(c => c.Name == "Predecessor").First();
250
251      connection.To.DetachFromParent();
252      connection.To.AttachTo(connectorTo);
253      this.graphVisualization.Invalidate();
254    }
255
256    private void RemoveConnection(IConnection connection) {
257      if (connection == null)
258        return;
259
260      if (connection.From.AttachedTo != null)
261        connection.From.DetachFromParent();
262      if (connection.To.AttachedTo != null)
263        connection.To.DetachFromParent();
264
265      if (this.connectionConnectorsMapping.ContainsFirst(connection))
266        this.connectionConnectorsMapping.RemoveByFirst(connection);
267      if (this.graphVisualization.Controller.Model.Connections.Contains(connection))
268        this.graphVisualization.Controller.Model.Remove(connection);
269      this.graphVisualization.Invalidate();
270    }
271
272
273    private void shapeInfo_Changed(object sender, ChangedEventArgs e) {
274      if (this.causedUpdateOfShapeInfo)
275        return;
276
277      IShapeInfo shapeInfo = (IShapeInfo)sender;
278      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
279      shapeInfo.UpdateShape(shape);
280      shape.Invalidate();
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.Content.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.Content.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.Content.RemoveConnection(shapeInfo, connectorName);
329      }
330    }
331
332    internal void RelayoutGraph() {
333      if (this.shapeInfoShapeMapping.Count > 0
334        && this.connectionConnectorsMapping.Count > 0
335        && this.Content.InitialShape != null) { //otherwise the layout does not work
336        string layoutName = "Standard TreeLayout";
337        this.graphVisualization.Controller.RunActivity(layoutName);
338        this.graphVisualization.Invalidate();
339
340        //fix to avoid negative shape positions after layouting
341        Thread.Sleep(100);
342        int minX = this.graphVisualization.Controller.Model.Shapes.Min(s => s.Location.X);
343        int shiftX = minX < 0 ? Math.Abs(minX) + 50 : 0;
344        int minY = this.graphVisualization.Controller.Model.Shapes.Min(s => s.Location.Y);
345        int shiftY = minY < 0 ? Math.Abs(minY) + 50 : 0;
346        if (minX < 0 || minY < 0) {
347          foreach (IShape s in this.Controller.Model.Shapes)
348            s.MoveBy(new Point(shiftX, shiftY));
349        }
350      }
351    }
352  }
353}
Note: See TracBrowser for help on using the repository browser.