Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Visualization/HeuristicLab.Visualization/3.3/ChartControl.cs @ 9491

Last change on this file since 9491 was 9491, checked in by bburlacu, 11 years ago

#1265: Added mouse wheel support to the picture box.

File size: 11.6 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.Drawing.Drawing2D;
26using System.Drawing.Imaging;
27using System.Windows.Forms;
28
29namespace HeuristicLab.Visualization {
30  public partial class ChartControl : UserControl {
31    private Bitmap bitmap;
32    public Bitmap Bitmap { get; private set; }
33    private bool renderingRequired;
34    private Point buttonDownPoint;
35    private Point mousePosition;
36    private int mouseClickCount;
37
38    private Chart myChart;
39    public Chart Chart {
40      get { return myChart; }
41      set {
42        if (myChart != null) myChart.Update -= new EventHandler(myChart_Update);
43        myChart = value;
44        if (myChart != null) {
45          myChart.Update += new EventHandler(myChart_Update);
46          SetMode(Chart.Mode);
47        }
48        GenerateImage();
49      }
50    }
51    private bool myScaleOnResize;
52    public bool ScaleOnResize {
53      get { return myScaleOnResize; }
54      set { myScaleOnResize = value; }
55    }
56
57    public ChartControl() {
58      InitializeComponent();
59      myScaleOnResize = true;
60      GenerateImage();
61    }
62
63    private void myChart_Update(object sender, EventArgs e) {
64      GenerateImage();
65    }
66    private void pictureBox_SizeChanged(object sender, EventArgs e) {
67      if (ScaleOnResize) {
68        if ((pictureBox.Width > 0) && (pictureBox.Height > 0) && (Chart != null)) {
69          PointD point = Chart.TransformPixelToWorld(new Point(pictureBox.Width, Chart.SizeInPixels.Height - pictureBox.Height));
70          Chart.SetPosition(Chart.LowerLeft, point);
71        }
72      }
73      GenerateImage();
74    }
75    private void pictureBox_VisibleChanged(object sender, EventArgs e) {
76      if (pictureBox.Visible && renderingRequired) {
77        GenerateImage();
78      }
79    }
80
81    private void pictureBox_MouseDown(object sender, MouseEventArgs e) {
82      buttonDownPoint = e.Location;
83      mouseClickCount = e.Clicks;
84    }
85    protected virtual void pictureBox_MouseUp(object sender, MouseEventArgs e) {
86      if (e.Button == MouseButtons.Left) {
87        if (Chart.Mode == ChartMode.Zoom) {
88          pictureBox.Refresh();
89          // some code to preserve the aspect ratio when zooming
90          //       +---------------------+ (Width,Height)
91          //       |  (x1,y1)            |
92          //       |      +-------+      |
93          //       |      |       |      |
94          //       |      |       |      |
95          //       |      +-------+      |
96          //       |             (x2,y2) |
97          // (0,0) +---------------------+
98          //
99          double aspectRatio = (double)Width / Height;
100          double x1 = Math.Min(e.X, buttonDownPoint.X);
101          double y1 = Math.Max(e.Y, buttonDownPoint.Y);
102          double x2 = Math.Max(e.X, buttonDownPoint.X);
103          double y2 = Math.Min(e.Y, buttonDownPoint.Y);
104          // consider the relative ratios between the X and Y dimensions of the selection
105          // area and the Width and Height, respectively. The "dominant" dimension is the
106          // one with a ratio closer to 1, and it stays fixed while the other is adjusted
107          // in order to preserve the aspect ratio
108          if ((x2 - x1) / Width > (y1 - y2) / Height) {
109            y1 = y2 + (x2 - x1) / aspectRatio;
110          } else {
111            x2 = aspectRatio * (y1 - y2) + x1;
112          }
113          var lowerLeft = new Point((int)x1, (int)y1);
114          var upperRight = new Point((int)x2, (int)y2);
115          if ((lowerLeft.X != upperRight.X) && (lowerLeft.Y != upperRight.Y)) {
116            Chart.ZoomIn(lowerLeft, upperRight);
117          }
118        }
119      } else if (e.Button == MouseButtons.Right) {
120        propertiesToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count == 1;
121        oneLayerUpToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count == 1;
122        oneLayerDownToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count == 1;
123        intoForegroundToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count == 1;
124        intoBackgroundToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count == 1;
125      } else if (e.Button == MouseButtons.Middle) {
126        if (Chart.Mode == ChartMode.Zoom) {
127          if (mouseClickCount == 1) Chart.ZoomOut();
128          else if (mouseClickCount == 2) Chart.Unzoom();
129        }
130      }
131      if (buttonDownPoint == e.Location) {
132        if (mouseClickCount == 1)
133          Chart.MouseClick(e.Location, e.Button);
134        else if (mouseClickCount == 2)
135          Chart.MouseDoubleClick(e.Location, e.Button);
136      }
137    }
138
139    protected virtual void pictureBox_MouseMove(object sender, MouseEventArgs e) {
140      var text = Chart.GetToolTipText(e.Location);
141      if (toolTip.GetToolTip(pictureBox) != text)
142        toolTip.SetToolTip(pictureBox, text);
143      Cursor cursor = Chart.GetCursor(e.Location);
144      if (cursor != null) pictureBox.Cursor = cursor;
145      else pictureBox.Cursor = Cursors.Default;
146
147      if (e.Button != MouseButtons.None) {
148        if ((Chart.Mode == ChartMode.Zoom) && (e.Button == MouseButtons.Left)) {
149          pictureBox.Refresh();
150          Graphics graphics = pictureBox.CreateGraphics();
151          Pen pen = new Pen(Color.Gray);
152          pen.DashStyle = DashStyle.Dash;
153          graphics.DrawRectangle(pen,
154                                 Math.Min(e.X, buttonDownPoint.X),
155                                 Math.Min(e.Y, buttonDownPoint.Y),
156                                 Math.Abs(e.X - buttonDownPoint.X),
157                                 Math.Abs(e.Y - buttonDownPoint.Y));
158          pen.Dispose();
159          graphics.Dispose();
160        }
161        Chart.MouseDrag(mousePosition, e.Location, e.Button);
162      } else {
163        Chart.MouseMove(mousePosition, e.Location);
164      }
165      mousePosition = e.Location;
166    }
167
168    protected virtual void pictureBox_MouseWheel(object sender, MouseEventArgs e) {
169      if (e.Delta > 0) {
170        // zoom in
171        double x1 = Chart.LowerLeft.X + Chart.Size.Width / 8;
172        double y1 = Chart.LowerLeft.Y + Chart.Size.Height / 8;
173        double x2 = Chart.UpperRight.X - Chart.Size.Width / 8;
174        double y2 = Chart.UpperRight.Y - Chart.Size.Height / 8;
175        Chart.ZoomIn(x1, y1, x2, y2);
176      } else if (e.Delta < 0) {
177        // zoom out
178        double x1 = Chart.LowerLeft.X - Chart.Size.Width / 8;
179        double y1 = Chart.LowerLeft.Y - Chart.Size.Height / 8;
180        double x2 = Chart.UpperRight.X + Chart.Size.Width / 8;
181        double y2 = Chart.UpperRight.Y + Chart.Size.Height / 8;
182        Chart.ZoomIn(x1, y1, x2, y2);
183      }
184    }
185
186    private void pictureBox_MouseEnter(object sender, EventArgs e) {
187      pictureBox.Focus();
188    }
189
190    protected virtual void ChartControl_KeyDown(object sender, KeyEventArgs e) {
191      if (Chart.Mode == ChartMode.Select) {
192        if (e.KeyCode == Keys.Delete) {
193          IList<IPrimitive> selected = Chart.Group.SelectedPrimitives;
194          Chart.UpdateEnabled = false;
195          foreach (IPrimitive primitive in selected)
196            Chart.Group.Remove(primitive);
197          Chart.UpdateEnabled = true;
198          Chart.EnforceUpdate();
199        }
200      }
201    }
202
203    private void moveToolStripMenuItem_Click(object sender, EventArgs e) {
204      SetMode(ChartMode.Move);
205    }
206    private void zoomToolStripMenuItem_Click(object sender, EventArgs e) {
207      SetMode(ChartMode.Zoom);
208    }
209    private void selectToolStripMenuItem_Click(object sender, EventArgs e) {
210      SetMode(ChartMode.Select);
211    }
212    private void oneLayerUpToolStripMenuItem_Click(object sender, EventArgs e) {
213      if (Chart.Group.SelectedPrimitives.Count == 1) {
214        Chart.Group.SelectedPrimitives[0].OneLayerUp();
215      }
216    }
217    private void oneLayerDownToolStripMenuItem_Click(object sender, EventArgs e) {
218      if (Chart.Group.SelectedPrimitives.Count == 1) {
219        Chart.Group.SelectedPrimitives[0].OneLayerDown();
220      }
221    }
222    private void intoForegroundToolStripMenuItem_Click(object sender, EventArgs e) {
223      if (Chart.Group.SelectedPrimitives.Count == 1) {
224        Chart.Group.SelectedPrimitives[0].IntoForeground();
225      }
226    }
227    private void intoBackgroundToolStripMenuItem_Click(object sender, EventArgs e) {
228      if (Chart.Group.SelectedPrimitives.Count == 1) {
229        Chart.Group.SelectedPrimitives[0].IntoBackground();
230      }
231    }
232    private void propertiesToolStripMenuItem_Click(object sender, EventArgs e) {
233      if (Chart.Group.SelectedPrimitives.Count == 1) {
234        PropertiesDialog dialog = new PropertiesDialog(Chart.Group.SelectedPrimitives[0]);
235        dialog.ShowDialog(this);
236        dialog.Dispose();
237      }
238    }
239
240    private void GenerateImage() {
241      if (!Visible) {
242        renderingRequired = true;
243      } else {
244        if ((pictureBox.Width == 0) || (pictureBox.Height == 0)) {
245          bitmap = null;
246        } else {
247          bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
248          if (Chart != null) {
249            Graphics graphics = Graphics.FromImage(bitmap);
250            graphics.SetClip(new System.Drawing.Rectangle(0, 0, pictureBox.Width, pictureBox.Height));
251            Chart.Render(graphics, pictureBox.Width, pictureBox.Height);
252            graphics.Dispose();
253          }
254        }
255        if (pictureBox.Image != null) pictureBox.Image.Dispose();
256        pictureBox.Image = bitmap;
257        renderingRequired = false;
258      }
259    }
260
261    private void SetMode(ChartMode mode) {
262      moveToolStripMenuItem.Checked = false;
263      zoomToolStripMenuItem.Checked = false;
264      selectToolStripMenuItem.Checked = false;
265      if (mode == ChartMode.Move) moveToolStripMenuItem.Checked = true;
266      else if (mode == ChartMode.Zoom) zoomToolStripMenuItem.Checked = true;
267      else if (mode == ChartMode.Select) selectToolStripMenuItem.Checked = true;
268      Chart.Mode = mode;
269    }
270
271    private void SaveImageAsBitmap(string filename) {
272      if (bitmap == null) throw new Exception("Bitmap is null.");
273      bitmap.Save(filename);
274    }
275
276    private void SaveImageAsEmf(string filename) {
277      using (Graphics g = CreateGraphics()) {
278        using (Metafile file = new Metafile(filename, g.GetHdc())) {
279          using (Graphics emfFile = Graphics.FromImage(file)) {
280            Chart.Render(emfFile, pictureBox.Width, pictureBox.Height);
281          }
282        }
283        g.ReleaseHdc();
284      }
285    }
286
287    private void saveImageToolStripMenuItem_Click(object sender, EventArgs e) {
288      if (saveFileDialog.ShowDialog() == DialogResult.OK) {
289        string filename = saveFileDialog.FileName.ToLower();
290        if (filename.EndsWith("bmp")) SaveImageAsBitmap(filename);
291        else if (filename.EndsWith("emf")) SaveImageAsEmf(filename);
292        else SaveImageAsBitmap(filename);
293      }
294    }
295  }
296}
Note: See TracBrowser for help on using the repository browser.