Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.3/SymbolicExpressionTreeChart.cs @ 4068

Last change on this file since 4068 was 4068, checked in by swagner, 14 years ago

Sorted usings and removed unused usings in entire solution (#1094)

File size: 12.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.Drawing;
25using System.Windows.Forms;
26
27namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
28  public sealed partial class SymbolicExpressionTreeChart : UserControl {
29    private Image image;
30    private StringFormat stringFormat;
31    private Dictionary<SymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode> visualTreeNodes;
32
33    public SymbolicExpressionTreeChart() {
34      InitializeComponent();
35      this.image = new Bitmap(Width, Height);
36      this.stringFormat = new StringFormat();
37      this.stringFormat.Alignment = StringAlignment.Center;
38      this.stringFormat.LineAlignment = StringAlignment.Center;
39      this.spacing = 5;
40      this.lineColor = Color.Black;
41      this.backgroundColor = Color.White;
42      this.textFont = new Font("Times New Roman", 8);
43    }
44
45    public SymbolicExpressionTreeChart(SymbolicExpressionTree tree)
46      : this() {
47      this.Tree = tree;
48    }
49
50    private int spacing;
51    public int Spacing {
52      get { return this.spacing; }
53      set {
54        this.spacing = value;
55        this.Repaint();
56      }
57    }
58
59    private Color lineColor;
60    public Color LineColor {
61      get { return this.lineColor; }
62      set {
63        this.lineColor = value;
64        this.Repaint();
65      }
66    }
67
68    private Color backgroundColor;
69    public Color BackgroundColor {
70      get { return this.backgroundColor; }
71      set {
72        this.backgroundColor = value;
73        this.Repaint();
74      }
75    }
76
77    private Font textFont;
78    public Font TextFont {
79      get { return this.textFont; }
80      set {
81        this.textFont = value;
82        this.Repaint();
83      }
84    }
85
86    private SymbolicExpressionTree tree;
87    public SymbolicExpressionTree Tree {
88      get { return this.tree; }
89      set {
90        tree = value;
91        visualTreeNodes = new Dictionary<SymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode>();
92        if (tree != null) {
93          foreach (SymbolicExpressionTreeNode node in tree.IterateNodesPrefix())
94            visualTreeNodes[node] = new VisualSymbolicExpressionTreeNode(node);
95        }
96        Repaint();
97      }
98    }
99
100    protected override void OnPaint(PaintEventArgs e) {
101      base.OnPaint(e);
102      e.Graphics.DrawImage(image, 0, 0);
103    }
104    protected override void OnResize(EventArgs e) {
105      base.OnResize(e);
106      if (this.Width == 0 || this.Height == 0)
107        this.image = new Bitmap(1, 1);
108      else
109        this.image = new Bitmap(Width, Height);
110      this.Repaint();
111    }
112
113    public void Repaint() {
114      this.GenerateImage();
115      this.Refresh();
116    }
117
118    private void GenerateImage() {
119      using (Graphics graphics = Graphics.FromImage(image)) {
120        graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
121        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
122        graphics.Clear(backgroundColor);
123        if (tree != null) {
124          int height = this.Height / tree.Height;
125          DrawFunctionTree(tree, graphics, 0, 0, this.Width, height);
126        }
127      }
128    }
129
130    public VisualSymbolicExpressionTreeNode GetVisualSymbolicExpressionTreeNode(SymbolicExpressionTreeNode symbolicExpressionTreeNode) {
131      if (visualTreeNodes.ContainsKey(symbolicExpressionTreeNode))
132        return visualTreeNodes[symbolicExpressionTreeNode];
133      return null;
134    }
135
136    #region events
137    public event MouseEventHandler SymbolicExpressionTreeNodeClicked;
138    private void OnSymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
139      var clicked = SymbolicExpressionTreeNodeClicked;
140      if (clicked != null)
141        clicked(sender, e);
142    }
143
144    private void SymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) {
145      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
146      if (visualTreeNode != null)
147        OnSymbolicExpressionTreeNodeClicked(visualTreeNode, e);
148    }
149
150    public event MouseEventHandler SymbolicExpressionTreeNodeDoubleClicked;
151    private void OnSymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
152      var doubleClicked = SymbolicExpressionTreeNodeDoubleClicked;
153      if (doubleClicked != null)
154        doubleClicked(sender, e);
155    }
156
157    private void SymbolicExpressionTreeChart_MouseDoubleClick(object sender, MouseEventArgs e) {
158      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
159      if (visualTreeNode != null)
160        OnSymbolicExpressionTreeNodeDoubleClicked(visualTreeNode, e);
161    }
162
163    public event ItemDragEventHandler SymbolicExpressionTreeNodeDrag;
164    private void OnSymbolicExpressionTreeNodeDragDrag(object sender, ItemDragEventArgs e) {
165      var dragged = SymbolicExpressionTreeNodeDrag;
166      if (dragged != null)
167        dragged(sender, e);
168    }
169
170    private VisualSymbolicExpressionTreeNode draggedSymbolicExpressionTree;
171    private MouseButtons dragButtons;
172    private void SymbolicExpressionTreeChart_MouseDown(object sender, MouseEventArgs e) {
173      this.dragButtons = e.Button;
174      this.draggedSymbolicExpressionTree = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
175    }
176    private void SymbolicExpressionTreeChart_MouseUp(object sender, MouseEventArgs e) {
177      this.draggedSymbolicExpressionTree = null;
178      this.dragButtons = MouseButtons.None;
179    }
180
181    private void SymbolicExpressionTreeChart_MouseMove(object sender, MouseEventArgs e) {
182      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
183      if (draggedSymbolicExpressionTree != null &&
184        draggedSymbolicExpressionTree != visualTreeNode) {
185        OnSymbolicExpressionTreeNodeDragDrag(draggedSymbolicExpressionTree, new ItemDragEventArgs(dragButtons, draggedSymbolicExpressionTree));
186        draggedSymbolicExpressionTree = null;
187      } else if (draggedSymbolicExpressionTree == null &&
188        visualTreeNode != null) {
189        string tooltipText = visualTreeNode.ToolTip;
190        if (this.toolTip.GetToolTip(this) != tooltipText)
191          this.toolTip.SetToolTip(this, tooltipText);
192
193      } else if (visualTreeNode == null)
194        this.toolTip.SetToolTip(this, "");
195    }
196
197    private VisualSymbolicExpressionTreeNode FindVisualSymbolicExpressionTreeNodeAt(int x, int y) {
198      foreach (var visualTreeNode in visualTreeNodes.Values) {
199        if (x >= visualTreeNode.X && x <= visualTreeNode.X + visualTreeNode.Width &&
200            y >= visualTreeNode.Y && y <= visualTreeNode.Y + visualTreeNode.Height)
201          return visualTreeNode;
202      }
203      return null;
204    }
205    #endregion
206
207    #region methods for painting the symbolic expression tree
208    private void DrawFunctionTree(SymbolicExpressionTree tree, Graphics graphics, int x, int y, int width, int height) {
209      DrawFunctionTree(tree.Root, graphics, x, y, width, height, Point.Empty);
210    }
211
212    /// <summary>
213    ///
214    /// </summary>
215    /// <param name="functionTree"> functiontree to draw</param>
216    /// <param name="graphics">graphics object to draw on</param>
217    /// <param name="x">x coordinate of drawing area</param>
218    /// <param name="y">y coordinate of drawing area</param>
219    /// <param name="width">width of drawing area</param>
220    /// <param name="height">height of drawing area</param>
221    private void DrawFunctionTree(SymbolicExpressionTreeNode node, Graphics graphics, int x, int y, int width, int height, Point connectionPoint) {
222      VisualSymbolicExpressionTreeNode visualTreeNode = visualTreeNodes[node];
223      float center_x = x + width / 2;
224      float center_y = y + height / 2;
225      int actualWidth = width - spacing;
226      int actualHeight = height - spacing;
227
228      SolidBrush textBrush = new SolidBrush(visualTreeNode.TextColor);
229      Pen linePen = new Pen(this.lineColor);
230      Pen nodeLinePen = new Pen(visualTreeNode.LineColor);
231      SolidBrush nodeFillBrush = new SolidBrush(visualTreeNode.FillColor);
232
233      //calculate size of node
234      if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
235        visualTreeNode.Width = visualTreeNode.PreferredWidth;
236        visualTreeNode.Height = visualTreeNode.PreferredHeight;
237        visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
238        visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
239      }
240        //width too small to draw in desired sized
241      else if (actualWidth < visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
242        visualTreeNode.Width = actualWidth;
243        visualTreeNode.Height = visualTreeNode.PreferredHeight;
244        visualTreeNode.X = x;
245        visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
246      }
247        //height too small to draw in desired sized
248      else if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight < visualTreeNode.PreferredHeight) {
249        visualTreeNode.Width = visualTreeNode.PreferredWidth;
250        visualTreeNode.Height = actualHeight;
251        visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
252        visualTreeNode.Y = y;
253      }
254        //width and height too small to draw in desired size
255      else {
256        visualTreeNode.Width = actualWidth;
257        visualTreeNode.Height = actualHeight;
258        visualTreeNode.X = x;
259        visualTreeNode.Y = y;
260      }
261
262      //draw terminal node
263      if (node.SubTrees.Count == 0) {
264        graphics.FillRectangle(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
265        graphics.DrawRectangle(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
266      } else {
267        graphics.FillEllipse(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
268        graphics.DrawEllipse(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
269      }
270
271      //draw name of symbol
272      var text = node.ToString();
273      graphics.DrawString(text, textFont, textBrush, new RectangleF(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height), stringFormat);
274
275      //draw connection line to parent node
276      if (!connectionPoint.IsEmpty)
277        graphics.DrawLine(linePen, connectionPoint, new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y));
278
279      //calculate areas for the subtrees according to their tree size and call drawFunctionTree
280      Point connectFrom = new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y + visualTreeNode.Height);
281      int[] xBoundaries = new int[node.SubTrees.Count + 1];
282      xBoundaries[0] = x;
283      for (int i = 0; i < node.SubTrees.Count; i++) {
284        xBoundaries[i + 1] = (int)(xBoundaries[i] + (width * (double)node.SubTrees[i].GetSize()) / (node.GetSize() - 1));
285        DrawFunctionTree(node.SubTrees[i], graphics, xBoundaries[i], y + height,
286          xBoundaries[i + 1] - xBoundaries[i], height, connectFrom);
287      }
288    }
289    #endregion
290  }
291}
Note: See TracBrowser for help on using the repository browser.