Free cookie consent management tool by TermsFeed Policy Generator

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

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

updated SymbolicExpressionTreeChart (ticket #938)

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