Free cookie consent management tool by TermsFeed Policy Generator

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

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

changed cursor when shapes are hovered (ticket #867)

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