Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 12008 was 11171, checked in by ascheibe, 10 years ago

#2115 merged r11170 (copyright update) into trunk

File size: 16.8 KB
RevLine 
[2893]1#region License Information
2/* HeuristicLab
[11171]3 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[2893]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.Drawing;
[4068]24using System.Drawing.Drawing2D;
[2893]25using System.Linq;
[4068]26using System.Threading;
[2893]27using System.Windows.Forms;
[4068]28using HeuristicLab.Collections;
[2893]29using HeuristicLab.MainForm;
[4068]30using HeuristicLab.MainForm.WindowsForms;
[2893]31using Netron.Diagramming.Core;
32
[6036]33namespace HeuristicLab.Operators.Views.GraphVisualization.Views {
[2917]34  [View("GraphVisualizationInfo View")]
[3386]35  [Content(typeof(IGraphVisualizationInfo), true)]
[3514]36  public partial class GraphVisualizationInfoView : AsynchronousContentView {
[9011]37    private BidirectionalDictionary<IShapeInfo, IShape> shapeInfoShapeMapping;
38    private BidirectionalDictionary<IConnectionInfo, IConnection> connectionInfoConnectionMapping;
[3386]39    private LinePenStyle connectionPenStyle;
[2893]40
41    public GraphVisualizationInfoView() {
42      InitializeComponent();
[9011]43      this.shapeInfoShapeMapping = new BidirectionalDictionary<IShapeInfo, IShape>();
44      this.connectionInfoConnectionMapping = new BidirectionalDictionary<IConnectionInfo, IConnection>();
[3386]45      this.connectionPenStyle = new LinePenStyle();
46      this.connectionPenStyle.EndCap = LineCap.ArrowAnchor;
[4809]47
48      PasteTool pasteTool = (PasteTool)this.Controller.Tools.Where(t => t.Name == ControllerBase.PasteToolName).FirstOrDefault();
49      CopyTool copyTool = (CopyTool)this.Controller.Tools.Where(t => t.Name == ControllerBase.CopyToolName).FirstOrDefault();
50      HeuristicLab.Netron.Controller controller = this.Controller as HeuristicLab.Netron.Controller;
[4814]51      if (controller != null) {
[4809]52        if (pasteTool != null) controller.RemoveTool(pasteTool);
53        if (copyTool != null) controller.RemoveTool(copyTool);
54      }
[2893]55    }
56
57    public IController Controller {
58      get { return this.graphVisualization.Controller; }
59    }
60
[3386]61    public new IGraphVisualizationInfo Content {
62      get { return (IGraphVisualizationInfo)base.Content; }
[2893]63      set { base.Content = value; }
64    }
65
66    protected override void OnContentChanged() {
67      base.OnContentChanged();
68      this.UpdateContent();
69    }
70
[3904]71    protected override void SetEnabledStateOfControls() {
72      base.SetEnabledStateOfControls();
[3386]73      DeleteTool deleteTool = (DeleteTool)this.Controller.Tools.Where(t => t.Name == ControllerBase.DeleteToolName).FirstOrDefault();
[3355]74      HeuristicLab.Netron.Controller controller = this.Controller as HeuristicLab.Netron.Controller;
75      if (Content == null && deleteTool != null && controller != null)
[3386]76        controller.RemoveTool(deleteTool);
[3355]77      else {
[3514]78        if ((ReadOnly || Locked) && deleteTool != null && controller != null)
[3355]79          controller.RemoveTool(deleteTool);
[3514]80        else if ((!ReadOnly && !Locked) && deleteTool == null)
[3355]81          this.Controller.AddTool(new DeleteTool(ControllerBase.DeleteToolName));
82      }
83    }
84
[2893]85    private void UpdateContent() {
[10366]86      foreach (IConnectionInfo connectionInfo in this.connectionInfoConnectionMapping.FirstKeys.ToList())
[3386]87        this.RemoveConnectionInfo(connectionInfo);
88      this.connectionInfoConnectionMapping.Clear();
[10366]89      foreach (IShapeInfo shapeInfo in this.shapeInfoShapeMapping.FirstKeys.ToList())
[2893]90        this.RemoveShapeInfo(shapeInfo);
91      this.shapeInfoShapeMapping.Clear();
92
[3355]93      if (Content != null) {
[3386]94        foreach (IShapeInfo shapeInfo in this.Content.ShapeInfos)
95          this.AddShapeInfo(shapeInfo);
96        foreach (IConnectionInfo connectionInfo in this.Content.ConnectionInfos)
97          this.AddConnectionInfo(connectionInfo);
[3355]98        this.UpdateLayoutRoot();
99      }
[2893]100    }
101    private void UpdateLayoutRoot() {
[3386]102      IShapeInfo shapeInfo = this.Content.InitialShape;
[2893]103      if (shapeInfo != null)
104        this.graphVisualization.Controller.Model.LayoutRoot = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
105      else
106        this.graphVisualization.Controller.Model.LayoutRoot = null;
107    }
108    private void VisualizationInfo_InitialShapeChanged(object sender, EventArgs e) {
109      this.UpdateLayoutRoot();
110    }
111
112    protected override void RegisterContentEvents() {
113      base.RegisterContentEvents();
114      this.Content.InitialShapeChanged += new EventHandler(VisualizationInfo_InitialShapeChanged);
115
[3386]116      this.Content.ObserveableShapeInfos.ItemsAdded += new CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsAdded);
117      this.Content.ObserveableShapeInfos.ItemsRemoved += new CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsRemoved);
118      this.Content.ObserveableShapeInfos.CollectionReset += new CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_CollectionReset);
119
120      this.Content.ObservableConnectionInfos.ItemsAdded += new CollectionItemsChangedEventHandler<IConnectionInfo>(ConnectionInfos_ItemsAdded);
121      this.Content.ObservableConnectionInfos.ItemsRemoved += new CollectionItemsChangedEventHandler<IConnectionInfo>(ConnectionInfos_ItemsRemoved);
122      this.Content.ObservableConnectionInfos.CollectionReset += new CollectionItemsChangedEventHandler<IConnectionInfo>(ConnectionInfos_CollectionReset);
[2893]123    }
124
125    protected override void DeregisterContentEvents() {
126      base.DeregisterContentEvents();
127      this.Content.InitialShapeChanged -= new EventHandler(VisualizationInfo_InitialShapeChanged);
128
[3386]129      this.Content.ObserveableShapeInfos.ItemsAdded -= new CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsAdded);
130      this.Content.ObserveableShapeInfos.ItemsRemoved -= new CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_ItemsRemoved);
131      this.Content.ObserveableShapeInfos.CollectionReset -= new CollectionItemsChangedEventHandler<IShapeInfo>(ShapeInfos_CollectionReset);
132
133      this.Content.ObservableConnectionInfos.ItemsAdded -= new CollectionItemsChangedEventHandler<IConnectionInfo>(ConnectionInfos_ItemsAdded);
134      this.Content.ObservableConnectionInfos.ItemsRemoved -= new CollectionItemsChangedEventHandler<IConnectionInfo>(ConnectionInfos_ItemsRemoved);
135      this.Content.ObservableConnectionInfos.CollectionReset -= new CollectionItemsChangedEventHandler<IConnectionInfo>(ConnectionInfos_CollectionReset);
[2893]136    }
137
[3386]138    #region ShapeInfos
139    private void ShapeInfos_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
140      foreach (IShapeInfo shapeInfo in e.OldItems)
[2893]141        this.RemoveShapeInfo(shapeInfo);
[3386]142      foreach (IShapeInfo shapeInfo in e.Items)
[2893]143        this.AddShapeInfo(shapeInfo);
144    }
[3386]145    private void ShapeInfos_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
146      foreach (IShapeInfo shapeInfo in e.Items)
[2893]147        this.AddShapeInfo(shapeInfo);
148    }
[3386]149    private void ShapeInfos_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IShapeInfo> e) {
150      foreach (IShapeInfo shapeInfo in e.Items)
[2893]151        this.RemoveShapeInfo(shapeInfo);
152    }
153
[3386]154    private void AddShapeInfo(IShapeInfo shapeInfo) {
[2893]155      this.RegisterShapeInfoEvents(shapeInfo);
156      IShape shape = shapeInfo.CreateShape();
[3386]157      this.RegisterShapeEvents(shape);
[2893]158      this.shapeInfoShapeMapping.Add(shapeInfo, shape);
159
160      this.graphVisualization.Controller.Model.AddShape(shape);
161      this.graphVisualization.Invalidate();
162    }
[3386]163    private void RemoveShapeInfo(IShapeInfo shapeInfo) {
[3514]164      this.DeregisterShapeInfoEvents(shapeInfo);
165      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
166      this.DeregisterShapeEvents(shape);
167      this.shapeInfoShapeMapping.RemoveByFirst(shapeInfo);
[2893]168
[3514]169      if (this.graphVisualization.Controller.Model.Shapes.Contains(shape)) {
170        this.graphVisualization.Controller.Model.RemoveShape(shape);
171        this.graphVisualization.Controller.Model.Selection.Clear();
172        this.graphVisualization.Invalidate();
173      }
[2893]174    }
175
176    private void RegisterShapeInfoEvents(IShapeInfo shapeInfo) {
[2934]177      shapeInfo.Changed += new EventHandler(shapeInfo_Changed);
[2893]178    }
179    private void DeregisterShapeInfoEvents(IShapeInfo shapeInfo) {
[2934]180      shapeInfo.Changed -= new EventHandler(shapeInfo_Changed);
[2893]181    }
182
[3386]183    private void shapeInfo_Changed(object sender, EventArgs e) {
184      IShapeInfo shapeInfo = (IShapeInfo)sender;
185      IShape shape = this.shapeInfoShapeMapping.GetByFirst(shapeInfo);
186      this.DeregisterShapeEvents(shape);
187      shapeInfo.UpdateShape(shape);
188      shape.Invalidate();
189      this.RegisterShapeEvents(shape);
[2893]190    }
[3386]191    #endregion
[2893]192
[3386]193    #region ConnectionInfos
194    private void ConnectionInfos_CollectionReset(object sender, CollectionItemsChangedEventArgs<IConnectionInfo> e) {
195      foreach (IConnectionInfo connectionInfo in e.Items)
196        this.RemoveConnectionInfo(connectionInfo);
197      foreach (IConnectionInfo connectionInfo in e.Items)
198        this.AddConnectionInfo(connectionInfo);
[2893]199    }
[3386]200    private void ConnectionInfos_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IConnectionInfo> e) {
201      foreach (IConnectionInfo connectionInfo in e.Items)
202        this.AddConnectionInfo(connectionInfo);
[2893]203    }
[3386]204    private void ConnectionInfos_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IConnectionInfo> e) {
205      foreach (IConnectionInfo connectionInfo in e.Items)
206        this.RemoveConnectionInfo(connectionInfo);
[2893]207    }
208
[3386]209    private void AddConnectionInfo(IConnectionInfo connectionInfo) {
210      this.RegisterConnectionInfoEvents(connectionInfo);
211      IShape shapeFrom = this.shapeInfoShapeMapping.GetByFirst(connectionInfo.From);
212      IShape shapeTo = this.shapeInfoShapeMapping.GetByFirst(connectionInfo.To);
[2893]213
[3386]214      IConnector connectorFrom = shapeFrom.Connectors.Where(c => c.Name == connectionInfo.ConnectorFrom).FirstOrDefault();
215      IConnector connectorTo = shapeTo.Connectors.Where(c => c.Name == connectionInfo.ConnectorTo).FirstOrDefault();
216      if (connectorFrom != null && connectorTo != null) {
217        Connection connection = new Connection(connectorFrom.Point, connectorTo.Point);
218        connection.From.AllowMove = false;
219        connection.To.AllowMove = false;
220        connectorFrom.AttachConnector(connection.From);
221        connectorTo.AttachConnector(connection.To);
222        connection.PenStyle = this.connectionPenStyle;
223        this.connectionInfoConnectionMapping.Add(connectionInfo, connection);
[2893]224        this.graphVisualization.Controller.Model.AddConnection(connection);
225        this.graphVisualization.Invalidate();
226      }
227    }
228
[3386]229    private void RemoveConnectionInfo(IConnectionInfo connectionInfo) {
230      DeregisterConnectionInfoEvents(connectionInfo);
231      IConnection connection = this.connectionInfoConnectionMapping.GetByFirst(connectionInfo);
232      this.connectionInfoConnectionMapping.RemoveByFirst(connectionInfo);
233      this.RemoveConnection(connection);
[3514]234
[2893]235    }
236    private void RemoveConnection(IConnection connection) {
237      if (connection.From.AttachedTo != null)
238        connection.From.DetachFromParent();
239      if (connection.To.AttachedTo != null)
240        connection.To.DetachFromParent();
[3386]241      if (this.Controller.Model.Connections.Contains(connection)) {
[2893]242        this.graphVisualization.Controller.Model.Remove(connection);
[3386]243        this.graphVisualization.Invalidate();
244      }
[2893]245    }
246
[3386]247    private void RegisterConnectionInfoEvents(IConnectionInfo connectionInfo) {
248      connectionInfo.Changed += new EventHandler(connectionInfo_Changed);
249    }
250    private void DeregisterConnectionInfoEvents(IConnectionInfo connectionInfo) {
251      connectionInfo.Changed -= new EventHandler(connectionInfo_Changed);
252    }
253    private void connectionInfo_Changed(object sender, EventArgs e) {
254      IConnectionInfo connectionInfo = (IConnectionInfo)sender;
255      IConnection connection = this.connectionInfoConnectionMapping.GetByFirst(connectionInfo);
256      this.RemoveConnectionInfo(connectionInfo);
257      this.AddConnectionInfo(connectionInfo);
258    }
259    #endregion
[2893]260
[3386]261    #region netron events - shapes, graphvisualization
262    private void RegisterShapeEvents(IShape shape) {
263      shape.OnEntityChange += new EventHandler<EntityEventArgs>(shape_OnEntityChange);
264      shape.OnMouseEnter += new EventHandler<EntityMouseEventArgs>(shape_OnMouseEnter);
265      shape.OnMouseLeave += new EventHandler<EntityMouseEventArgs>(shape_OnMouseLeave);
266    }
[2893]267
[3386]268    private void DeregisterShapeEvents(IShape shape) {
269      shape.OnEntityChange -= new EventHandler<EntityEventArgs>(shape_OnEntityChange);
270      shape.OnMouseEnter -= new EventHandler<EntityMouseEventArgs>(shape_OnMouseEnter);
271      shape.OnMouseLeave -= new EventHandler<EntityMouseEventArgs>(shape_OnMouseLeave);
[2893]272    }
273
[3171]274    private Cursor oldCursor;
275    private void shape_OnMouseEnter(object sender, EntityMouseEventArgs e) {
276      this.oldCursor = this.Cursor;
277      this.Controller.View.CurrentCursor = CursorPalette.Move;
278    }
[2893]279
[3171]280    private void shape_OnMouseLeave(object sender, EntityMouseEventArgs e) {
281      this.Controller.View.CurrentCursor = this.oldCursor;
282      this.oldCursor = null;
283    }
284
[2893]285    private void shape_OnEntityChange(object sender, EntityEventArgs e) {
286      IShape shape = e.Entity as IShape;
[3386]287      IShapeInfo shapeInfo = this.shapeInfoShapeMapping.GetBySecond(shape);
288      this.DeregisterShapeInfoEvents(shapeInfo);
289      shapeInfo.UpdateShapeInfo(shape);
290      this.RegisterShapeInfoEvents(shapeInfo);
[2893]291      this.graphVisualization.Invalidate();
292    }
293
[3386]294
[2893]295    private void graphVisualization_OnEntityAdded(object sender, EntityEventArgs e) {
296      IConnection connection = e.Entity as IConnection;
[3386]297      if (connection != null && !this.connectionInfoConnectionMapping.ContainsSecond(connection)) {
[2893]298        IConnector connectorFrom = connection.From.AttachedTo;
299        IConnector connectorTo = connection.To.AttachedTo;
300        this.RemoveConnection(connection); //is added again by the model events
301
[3386]302        if (connectorFrom != null && connectorTo != null) {
[2893]303          IShape shapeFrom = (IShape)connectorFrom.Parent;
304          IShape shapeTo = (IShape)connectorTo.Parent;
[3386]305          IShapeInfo shapeInfoFrom = this.shapeInfoShapeMapping.GetBySecond(shapeFrom);
306          IShapeInfo shapeInfoTo = this.shapeInfoShapeMapping.GetBySecond(shapeTo);
307          string connectorFromName = connectorFrom.Name;
308          string connectorToName = connectorTo.Name;
[2893]309
[3386]310          if (shapeInfoFrom != shapeInfoTo) //avoid self references
311            this.Content.AddConnectionInfo(new ConnectionInfo(shapeInfoFrom, connectorFromName, shapeInfoTo, connectorToName));
[2893]312        }
313      }
314    }
315
316    private void graphVisualization_OnEntityRemoved(object sender, EntityEventArgs e) {
317      IShape shape = e.Entity as IShape;
318      if (shape != null && this.shapeInfoShapeMapping.ContainsSecond(shape)) {
[3386]319        IShapeInfo shapeInfo = this.shapeInfoShapeMapping.GetBySecond(shape);
[2893]320        this.Content.RemoveShapeInfo(shapeInfo);
321      }
322
323      IConnection connection = e.Entity as IConnection;
[3386]324      if (connection != null && this.connectionInfoConnectionMapping.ContainsSecond(connection)) {
325        IConnectionInfo connectionInfo = connectionInfoConnectionMapping.GetBySecond(connection);
326        this.Content.RemoveConnectionInfo(connectionInfo);
[2893]327      }
328    }
[3386]329    #endregion
[2893]330
[3386]331    public void RelayoutGraph() {
[2893]332      if (this.shapeInfoShapeMapping.Count > 0
[3386]333        && this.connectionInfoConnectionMapping.Count > 0
[2893]334        && this.Content.InitialShape != null) { //otherwise the layout does not work
335        string layoutName = "Standard TreeLayout";
336        this.graphVisualization.Controller.RunActivity(layoutName);
337        this.graphVisualization.Invalidate();
[2909]338
339        //fix to avoid negative shape positions after layouting
[3186]340        Thread.Sleep(300);
[2909]341        int minX = this.graphVisualization.Controller.Model.Shapes.Min(s => s.Location.X);
342        int shiftX = minX < 0 ? Math.Abs(minX) + 50 : 0;
343        int minY = this.graphVisualization.Controller.Model.Shapes.Min(s => s.Location.Y);
344        int shiftY = minY < 0 ? Math.Abs(minY) + 50 : 0;
345        if (minX < 0 || minY < 0) {
346          foreach (IShape s in this.Controller.Model.Shapes)
347            s.MoveBy(new Point(shiftX, shiftY));
348        }
[2893]349      }
350    }
351  }
352}
Note: See TracBrowser for help on using the repository browser.