source: branches/OptimizationNetworks/HeuristicLab.Networks.Views.NetworkVisualization/3.3/Primitives/NodeRectangle.cs @ 13799

Last change on this file since 13799 was 13799, checked in by jkarder, 3 years ago

#2205: worked on optimization networks

  • improved network visualization
File size: 13.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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.Drawing;
25using System.Drawing.Drawing2D;
26using System.Windows.Forms;
27using HeuristicLab.Common;
28using HeuristicLab.Core.Networks;
29using HeuristicLab.Visualization;
30
31namespace HeuristicLab.Networks.Views.NetworkVisualization {
32  [Primitive(typeof(INode), true)]
33  public class NodeRectangle : Visualization.Rectangle, INetworkItemPrimitive<INode> {
34    protected readonly Dictionary<IPort, IPrimitive> port2primitive = new Dictionary<IPort, IPrimitive>();
35    protected readonly IGroup portRectangles;
36
37    protected INodeVisualProperties VisualProperties {
38      get { return (INodeVisualProperties)networkItem.VisualProperties; }
39      set {
40        if (networkItem.VisualProperties == value) return;
41        networkItem.VisualProperties = value;
42      }
43    }
44    protected bool IgnoreVisualPropertiesChanges { get; set; }
45
46    protected INode networkItem;
47    public INode NetworkItem {
48      get { return networkItem; }
49      set {
50        if (networkItem == value) return;
51        if (networkItem != null) DeregisterNetworkItemEvents();
52        networkItem = value;
53        if (networkItem != null) RegisterNetworkItemEvents();
54        LoadVisualProperties();
55        OnNetworkItemChanged();
56      }
57    }
58
59    public override Brush Brush {
60      get { return base.Brush; }
61      set {
62        if (base.Brush == value) return;
63        base.Brush = value;
64        SaveVisualProperties();
65      }
66    }
67
68    public override Pen Pen {
69      get { return base.Pen; }
70      set {
71        if (base.Pen == value) return;
72        base.Pen = value;
73        SaveVisualProperties();
74      }
75    }
76
77    public NodeRectangle(IChart chart, INode node)
78      : base(chart, PointD.Empty, PointD.Empty) {
79      bool adjustSize = node.VisualProperties == null;
80      NetworkItem = node;
81
82      portRectangles = new Group(chart);
83      foreach (var port in node.Ports) {
84        var portPrimitive = PrimitiveAttribute.CreateDefaultPrimitive(port.GetType(), chart, port, node); // TODO: port.Parent != node
85        port2primitive.Add(port, portPrimitive);
86        portRectangles.Add(portPrimitive);
87      }
88      portRectangles.RedrawRequired += (sender, args) => OnRedrawRequired();
89
90      if (adjustSize) AdjustSize();
91    }
92
93    protected virtual void RegisterNetworkItemEvents() {
94      if (VisualProperties != null) {
95        VisualProperties.Changed += VisualProperties_Changed;
96      }
97      networkItem.NameChanged += NetworkItem_NameChanged;
98      if (networkItem.Ports != null) {
99        networkItem.Ports.ItemsAdded += Ports_ItemsAdded;
100        networkItem.Ports.ItemsRemoved += Ports_ItemsRemoved;
101      }
102    }
103
104    protected virtual void DeregisterNetworkItemEvents() {
105      if (VisualProperties != null) {
106        VisualProperties.Changed -= VisualProperties_Changed;
107      }
108      networkItem.NameChanged -= NetworkItem_NameChanged;
109      if (networkItem.Ports != null) {
110        networkItem.Ports.ItemsAdded -= Ports_ItemsAdded;
111        networkItem.Ports.ItemsRemoved -= Ports_ItemsRemoved;
112      }
113    }
114
115    #region Overrides
116    public override void SetPosition(PointD lowerLeft, PointD upperRight) {
117      base.SetPosition(lowerLeft, upperRight);
118      SaveVisualProperties();
119    }
120
121    public override void Draw(Graphics graphics) {
122      int cornerRadius = (int)Math.Round(6 * Chart.WorldToPixelRatio.Width);
123      var point = Chart.TransformWorldToPixel(new PointD(LowerLeft.X, LowerLeft.Y + Size.Height));
124      var size = Chart.TransformWorldToPixel(Size);
125      var bounds = new System.Drawing.Rectangle(point.X, point.Y, size.Width, size.Height);
126      var arc = new System.Drawing.Rectangle(point, new Size(cornerRadius * 2, cornerRadius * 2));
127
128      using (var path = new GraphicsPath()) {
129        path.AddArc(arc, 180f, 90f);
130        arc.X = bounds.Right - cornerRadius * 2;
131        path.AddArc(arc, 270f, 90);
132        arc.Y = bounds.Bottom - cornerRadius * 2;
133        path.AddArc(arc, 0f, 90f);
134        arc.X = bounds.Left;
135        path.AddArc(arc, 90f, 90f);
136        path.CloseFigure();
137
138        graphics.FillPath(Brush, path);
139        graphics.DrawPath(Pen, path);
140      }
141
142      var p = Chart.TransformWorldToPixel(new PointD(LowerLeft.X, LowerLeft.Y + Size.Height));
143
144      if (networkItem != null) {
145        using (var headerFont = new Font(FontFamily.GenericSansSerif, (float)Math.Round(8.25 * Chart.WorldToPixelRatio.Width), FontStyle.Bold))
146        using (var contentFont = new Font(FontFamily.GenericSansSerif, (float)Math.Round(8.25 * Chart.WorldToPixelRatio.Width))) {
147          int margin = 4, x, y, lastY;
148
149          x = p.X + (int)Math.Round(margin * Chart.WorldToPixelRatio.Width);
150          y = p.Y + (int)Math.Round(margin * Chart.WorldToPixelRatio.Height);
151
152          var imageSize = networkItem.ItemImage.Size;
153          float imageWidth = (float)Math.Round(imageSize.Width * Chart.WorldToPixelRatio.Width);
154          float imageHeight = (float)Math.Round(imageSize.Height * Chart.WorldToPixelRatio.Height);
155          graphics.DrawImage(networkItem.ItemImage, x, y, imageWidth, imageHeight);
156          lastY = y;
157
158          var textSize = graphics.MeasureString(networkItem.Name, headerFont);
159          x += (int)Math.Round((imageSize.Width + margin) * Chart.WorldToPixelRatio.Width);
160          y += (int)Math.Round((imageSize.Height - textSize.Height * Chart.PixelToWorldRatio.Height) / 2 * Chart.WorldToPixelRatio.Height);
161          graphics.DrawString(networkItem.Name, headerFont, Brushes.Black, x, y);
162          y = lastY + (int)Math.Round(imageSize.Height * Chart.WorldToPixelRatio.Height);
163
164          x = p.X;
165          y += (int)Math.Round(margin * Chart.WorldToPixelRatio.Height);
166          graphics.DrawLine(Pen, x, y, x + size.Width, y);
167
168          foreach (var port in networkItem.Ports) {
169            x = p.X + (int)Math.Round(margin * Chart.WorldToPixelRatio.Width);
170            y += (int)Math.Round(margin * Chart.WorldToPixelRatio.Height);
171
172            imageSize = port.ItemImage.Size;
173            imageWidth = (float)Math.Round(imageSize.Width * Chart.WorldToPixelRatio.Width);
174            imageHeight = (float)Math.Round(imageSize.Height * Chart.WorldToPixelRatio.Height);
175            graphics.DrawImage(port.ItemImage, x, y, imageWidth, imageHeight);
176            lastY = y;
177
178            textSize = graphics.MeasureString(port.Name, contentFont);
179            x += (int)Math.Round((imageSize.Width + margin) * Chart.WorldToPixelRatio.Width);
180            y += (int)Math.Round((imageSize.Height - textSize.Height * Chart.PixelToWorldRatio.Height) / 2 * Chart.WorldToPixelRatio.Height);
181            graphics.DrawString(port.Name, contentFont, Brushes.Black, x, y);
182            y = lastY + (int)Math.Round(imageSize.Height * Chart.WorldToPixelRatio.Height);
183
184            var parameterizedPort = port as IParameterizedPort;
185            if (parameterizedPort != null) {
186              foreach (var param in parameterizedPort.Parameters) {
187                x = p.X + (int)Math.Round(4 * margin * Chart.WorldToPixelRatio.Width);
188                y += (int)Math.Round(margin * Chart.WorldToPixelRatio.Height);
189
190                imageSize = param.ItemImage.Size;
191                imageWidth = (float)Math.Round(imageSize.Width * Chart.WorldToPixelRatio.Width);
192                imageHeight = (float)Math.Round(imageSize.Height * Chart.WorldToPixelRatio.Height);
193                graphics.DrawImage(param.ItemImage, x, y, imageWidth, imageHeight);
194                lastY = y;
195
196                textSize = graphics.MeasureString(param.Name, contentFont);
197                x += (int)Math.Round((imageSize.Width + margin) * Chart.WorldToPixelRatio.Width);
198                y += (int)Math.Round((imageSize.Height - textSize.Height * Chart.PixelToWorldRatio.Height) / 2 * Chart.WorldToPixelRatio.Height);
199                graphics.DrawString(param.Name, contentFont, Brushes.Black, x, y);
200                y = lastY + (int)Math.Round(imageSize.Height * Chart.WorldToPixelRatio.Height);
201              }
202            }
203          }
204        }
205      }
206
207      portRectangles.Draw(graphics);
208    }
209    #endregion
210
211    public IPrimitive GetPortPrimitive(IPort name) {
212      IPrimitive portPrimitive;
213      port2primitive.TryGetValue(name, out portPrimitive);
214      return portPrimitive;
215    }
216
217    #region Events
218    public event EventHandler NetworkItemChanged;
219    protected virtual void OnNetworkItemChanged() {
220      var handler = NetworkItemChanged;
221      if (handler != null) handler(this, EventArgs.Empty);
222    }
223    #endregion
224
225    #region Event Handlers
226    private void VisualProperties_Changed(object sender, EventArgs e) {
227      if (IgnoreVisualPropertiesChanges) return;
228
229      LoadVisualProperties();
230    }
231
232    private void NetworkItem_NameChanged(object sender, EventArgs e) { OnRedrawRequired(); }
233
234    private void Ports_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
235      AdjustSize();
236
237      foreach (var port in e.Items) {
238        var portRectangle = PrimitiveAttribute.CreateDefaultPrimitive(port.GetType(), Chart, port, networkItem);
239        port2primitive.Add(port, portRectangle);
240        portRectangles.Add(portRectangle);
241      }
242    }
243
244    private void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
245      AdjustSize();
246
247      foreach (var port in e.Items) {
248        var portRectangle = port2primitive[port];
249        port2primitive.Remove(port);
250        portRectangles.Remove(portRectangle);
251      }
252    }
253    #endregion
254
255    #region Helpers
256    private void LoadVisualProperties() {
257      if (VisualProperties == null)
258        VisualProperties = new NodeVisualProperties();
259
260      var vp = VisualProperties;
261      IgnoreVisualPropertiesChanges = true;
262      try {
263        SetPosition(new PointD(vp.LowerLeft.X, vp.LowerLeft.Y), new PointD(vp.UpperRight.X, vp.UpperRight.Y));
264        Brush = new SolidBrush(vp.BrushColor);
265        Pen = new Pen(vp.PenColor);
266      } finally { IgnoreVisualPropertiesChanges = false; }
267    }
268
269    private void SaveVisualProperties() {
270      if (networkItem == null || IgnoreVisualPropertiesChanges) return;
271
272      var vp = VisualProperties;
273      IgnoreVisualPropertiesChanges = true;
274      try {
275        vp.LowerLeft = new Point2D<double>(LowerLeft.X, LowerLeft.Y);
276        vp.UpperRight = new Point2D<double>(UpperRight.X, UpperRight.Y);
277        vp.BrushColor = ((SolidBrush)Brush).Color;
278        vp.PenColor = Pen.Color;
279      } finally { IgnoreVisualPropertiesChanges = false; }
280    }
281
282    private void AdjustSize() {
283      if (networkItem == null) return;
284
285      var p = Chart.TransformWorldToPixel(new PointD(LowerLeft.X, LowerLeft.Y + Size.Height));
286      int margin = 4, x = p.X, y = p.Y;
287      using (var headerFont = new Font(FontFamily.GenericSansSerif, (float)Math.Round(8.25), FontStyle.Bold))
288      using (var contentFont = new Font(FontFamily.GenericSansSerif, (float)Math.Round(8.25))) {
289        x += 2 * margin; y += 2 * margin;
290        int headerWidth = networkItem.ItemImage.Width + margin + TextRenderer.MeasureText(networkItem.Name, headerFont).Width;
291        y += networkItem.ItemImage.Height + margin;
292        int maxPortWidth = 0, maxPortParamWidth = 0;
293        foreach (var port in networkItem.Ports) {
294          int portWidth = port.ItemImage.Width + margin + TextRenderer.MeasureText(port.Name, contentFont).Width;
295          if (portWidth > maxPortWidth) maxPortWidth = portWidth;
296          y += margin + port.ItemImage.Height;
297          var parameterizedPort = port as IParameterizedPort;
298          if (parameterizedPort != null) {
299            foreach (var param in parameterizedPort.Parameters) {
300              int portParamWidth = param.ItemImage.Width + 3 * margin + TextRenderer.MeasureText(param.Name, contentFont).Width;
301              if (portParamWidth > maxPortParamWidth) maxPortParamWidth = portParamWidth;
302              y += margin + param.ItemImage.Height;
303            }
304          }
305        }
306
307        x += Math.Max(headerWidth, Math.Max(maxPortWidth, maxPortParamWidth));
308        var ll = Chart.TransformPixelToWorld(new Point(p.X, y));
309        var ur = Chart.TransformPixelToWorld(new Point(x, p.Y));
310        SetPosition(ll, ur);
311      }
312    }
313    #endregion
314  }
315}
Note: See TracBrowser for help on using the repository browser.