Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GP.Grammar.Editor/HeuristicLab.Operators.Views.GraphVisualization.Views/3.3/OperatorShape.cs @ 6902

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

#1486: Decoupled operator graph visualization content classes from view classes.

File size: 10.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.Linq;
27using HeuristicLab.Netron;
28using Netron.Diagramming.Core;
29
30namespace HeuristicLab.Operators.Views.GraphVisualization.Views {
31  public class OperatorShape : ComplexShapeBase {
32    private static int LABEL_HEIGHT = 16;
33    private static int LABEL_WIDTH = 180;
34    private static int LABEL_SPACING = 3;
35    private int headerHeight = 30;
36
37    private ExpandableIconMaterial expandIconMaterial;
38    public OperatorShape()
39      : base() {
40      this.Resizable = false;
41      this.additionalConnectors = new List<IConnector>();
42      this.labels = new List<string>();
43    }
44
45    public override string EntityName {
46      get { return "Operator Shape"; }
47    }
48
49    public bool Collapsed {
50      get { return this.expandIconMaterial.Collapsed; }
51      set {
52        if (this.expandIconMaterial.Collapsed != value)
53          this.expandIconMaterial.Collapsed = value;
54      }
55    }
56
57    private Color lineColor;
58    public Color LineColor {
59      get { return this.lineColor; }
60      set { this.lineColor = value; }
61    }
62
63    private float lineWidth;
64    public float LineWidth {
65      get { return this.lineWidth; }
66      set { this.lineWidth = value; }
67    }
68
69    private Color color;
70    public Color Color {
71      get { return this.color; }
72      set { this.color = value; }
73    }
74
75    private string title;
76    public string Title {
77      get { return title; }
78      set { title = value; }
79    }
80
81    private IconMaterial iconMaterial;
82    public Bitmap Icon {
83      get { return this.iconMaterial.Icon; }
84      set {
85        this.iconMaterial.Icon = value;
86        this.iconMaterial.Transform(new Rectangle(new Point(Rectangle.X + 5, Rectangle.Y + 5), this.iconMaterial.Icon.Size));
87      }
88    }
89
90    #region additional connectors
91    private List<IConnector> additionalConnectors;
92    public IEnumerable<string> AdditionalConnectorNames {
93      get { return this.additionalConnectors.Select(c => c.Name); }
94    }
95
96    private IConnector predecessor;
97    public IConnector Predecessor {
98      get { return this.predecessor; }
99    }
100
101    private IConnector successor;
102    public IConnector Successor {
103      get { return this.successor; }
104    }
105
106    private IConnector CreateConnector(string connectorName, Point location) {
107      Connector connector = new Connector(location, this.Model);
108      connector.ConnectorStyle = ConnectorStyle.Square;
109      connector.Parent = this;
110      connector.Name = connectorName;
111      return connector;
112    }
113
114    public void AddConnector(string connectorName) {
115      IConnector connector = this.CreateConnector(connectorName, this.BottomRightCorner);
116
117      this.additionalConnectors.Add(connector);
118      this.Connectors.Add(connector);
119      this.UpdateConnectorLocation();
120    }
121
122    public void RemoveConnector(string connectorName) {
123      IConnector connector = this.additionalConnectors.Where(c => c.Name == connectorName).FirstOrDefault();
124      if (connector != null) {
125        this.additionalConnectors.Remove(connector);
126        this.Connectors.Remove(connector);
127        this.UpdateConnectorLocation();
128      }
129    }
130
131    private void UpdateConnectorLocation() {
132      if (this.additionalConnectors.Count == 0)
133        return;
134
135      int spacing = this.Rectangle.Width / this.additionalConnectors.Count;
136      int margin = spacing / 2;
137      int posX = margin + this.Rectangle.X;
138      for (int i = 0; i < this.additionalConnectors.Count; i++) {
139        this.additionalConnectors[i].MoveBy(new Point(posX - this.additionalConnectors[i].Point.X, 0));
140        posX += spacing;
141      }
142    }
143    #endregion
144
145    #region label material
146    private List<string> labels;
147    public IEnumerable<string> Labels {
148      get { return this.labels; }
149    }
150
151    public void UpdateLabels(IEnumerable<string> labels) {
152      this.labels = new List<string>(labels);
153      this.expandIconMaterial.Visible = this.labels.Count != 0;
154      this.UpdateLabels();
155    }
156    #endregion
157
158    private void expandIconMaterial_OnExpand(object sender, EventArgs e) {
159      this.UpdateLabels();
160    }
161
162    private void expandIconMaterial_OnCollapse(object sender, EventArgs e) {
163      this.UpdateLabels();
164    }
165
166    private Size CalculateSize() {
167      int width = this.Rectangle.Width;
168      int height = headerHeight;
169      if (!Collapsed)
170        height += this.labels.Count * (LABEL_HEIGHT + LABEL_SPACING);
171      return new Size(width, height);
172    }
173
174    private void UpdateLabels() {
175      Size newSize = CalculateSize();
176      if (this.Rectangle.Size != newSize) {
177        foreach (IConnector connector in this.additionalConnectors)
178          connector.MoveBy(new Point(0, newSize.Height - this.Rectangle.Height));
179        this.mRectangle = new Rectangle(this.Rectangle.Location, newSize);
180        this.Invalidate();
181        this.RaiseOnChange(this, new EntityEventArgs(this));
182      }
183    }
184
185    protected override void Initialize() {
186      base.Initialize();
187
188      //the initial size
189      this.Transform(0, 0, 200, headerHeight);
190      this.color = Color.LightBlue;
191
192      this.iconMaterial = new IconMaterial();
193      this.iconMaterial.Gliding = false;
194      this.Children.Add(iconMaterial);
195
196      Bitmap expandBitmap = new Bitmap(HeuristicLab.Common.Resources.VSImageLibrary.Expand);
197      Bitmap collapseBitmap = new Bitmap(HeuristicLab.Common.Resources.VSImageLibrary.Collapse);
198      this.expandIconMaterial = new ExpandableIconMaterial(expandBitmap, collapseBitmap);
199      this.expandIconMaterial.Gliding = false;
200      this.expandIconMaterial.Transform(new Rectangle(new Point(Rectangle.Right - 20, Rectangle.Y + 7), expandIconMaterial.Icon.Size));
201      this.expandIconMaterial.Visible = false;
202      this.expandIconMaterial.OnExpand += new EventHandler(expandIconMaterial_OnExpand);
203      this.expandIconMaterial.OnCollapse += new EventHandler(expandIconMaterial_OnCollapse);
204      this.Children.Add(expandIconMaterial);
205
206      this.predecessor = this.CreateConnector(OperatorShapeInfoFactory.PredecessorConnector, new Point(Rectangle.Left, Center.Y));
207      this.Connectors.Add(predecessor);
208
209      this.successor = this.CreateConnector(OperatorShapeInfoFactory.SuccessorConnector, (new Point(Rectangle.Right, Center.Y)));
210      this.Connectors.Add(successor);
211    }
212
213    public override void Paint(Graphics g) {
214      base.Paint(g);
215
216      g.SmoothingMode = SmoothingMode.HighQuality;
217
218      Pen pen = new Pen(lineColor, lineWidth);
219
220      SizeF titleSize = g.MeasureString(this.Title, ArtPalette.DefaultBoldFont, Rectangle.Width - 45);
221      if (titleSize.Height + 10 > Rectangle.Height) {
222        headerHeight = (int)titleSize.Height + 10;
223        this.UpdateLabels();
224      }
225
226      GraphicsPath path = new GraphicsPath();
227      path.AddArc(Rectangle.X, Rectangle.Y, 20, 20, -180, 90);
228      path.AddLine(Rectangle.X + 10, Rectangle.Y, Rectangle.X + Rectangle.Width - 10, Rectangle.Y);
229      path.AddArc(Rectangle.X + Rectangle.Width - 20, Rectangle.Y, 20, 20, -90, 90);
230      path.AddLine(Rectangle.X + Rectangle.Width, Rectangle.Y + 10, Rectangle.X + Rectangle.Width, Rectangle.Y + Rectangle.Height - 10);
231      path.AddArc(Rectangle.X + Rectangle.Width - 20, Rectangle.Y + Rectangle.Height - 20, 20, 20, 0, 90);
232      path.AddLine(Rectangle.X + Rectangle.Width - 10, Rectangle.Y + Rectangle.Height, Rectangle.X + 10, Rectangle.Y + Rectangle.Height);
233      path.AddArc(Rectangle.X, Rectangle.Y + Rectangle.Height - 20, 20, 20, 90, 90);
234      path.AddLine(Rectangle.X, Rectangle.Y + Rectangle.Height - 10, Rectangle.X, Rectangle.Y + 10);
235      //shadow
236      if (ArtPalette.EnableShadows) {
237        Region darkRegion = new Region(path);
238        darkRegion.Translate(5, 5);
239        g.FillRegion(ArtPalette.ShadowBrush, darkRegion);
240      }
241      //background
242      g.FillPath(Brush, path);
243
244      using (LinearGradientBrush gradientBrush = new LinearGradientBrush(Rectangle.Location, new Point(Rectangle.X + Rectangle.Width, Rectangle.Y), this.Color, Color.White)) {
245        Region gradientRegion = new Region(path);
246        g.FillRegion(gradientBrush, gradientRegion);
247      }
248
249      if (!this.Collapsed) {
250        TextStyle textStyle = new TextStyle(Color.Black, new Font("Arial", 7), StringAlignment.Near, StringAlignment.Near);
251        StringFormat stringFormat = textStyle.StringFormat;
252        stringFormat.Trimming = StringTrimming.EllipsisWord;
253        stringFormat.FormatFlags = StringFormatFlags.LineLimit;
254        Rectangle rect;
255
256        for (int i = 0; i < this.labels.Count; i++) {
257          rect = new Rectangle(Rectangle.X + 25, Rectangle.Y + headerHeight + i * (LABEL_HEIGHT + LABEL_SPACING), LABEL_WIDTH, LABEL_HEIGHT);
258          g.DrawString(textStyle.GetFormattedText(this.labels[i]), textStyle.Font, textStyle.GetBrush(), rect, stringFormat);
259        }
260      }
261
262      //the border
263      g.DrawPath(pen, path);
264
265      //the title
266      g.DrawString(this.Title, ArtPalette.DefaultBoldFont, Brushes.Black, new Rectangle(Rectangle.X + 25, Rectangle.Y + 5, Rectangle.Width - 45, Rectangle.Height - 5));
267
268
269      //the material
270      foreach (IPaintable material in Children)
271        material.Paint(g);
272
273      //the connectors
274      if (this.ShowConnectors) {
275        for (int k = 0; k < Connectors.Count; k++)
276          Connectors[k].Paint(g);
277      }
278    }
279  }
280}
Note: See TracBrowser for help on using the repository browser.