Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 13112 was 13106, checked in by jkarder, 9 years ago

#1265: fixed bug in ChartControl

File size: 12.7 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.ComponentModel;
25using System.Drawing;
26using System.Drawing.Imaging;
27using System.Linq;
28using System.Windows.Forms;
29
30namespace HeuristicLab.Visualization {
31  public partial class ChartControl : UserControl {
32    protected Bitmap Picture;
33    protected bool RenderingRequired;
34    protected Dictionary<Type, ChartMode> Modes = new Dictionary<Type, ChartMode>();
35
36    protected bool SuppressEvents { get; set; }
37    private bool SuppressRender { get; set; }
38
39    public PictureBox PictureBox { get { return pictureBox; } }
40
41    public Color BackgroundColor {
42      get { return chart != null ? chart.BackgroundColor : Color.Empty; }
43      set {
44        if (chart == null || chart.BackgroundColor == value) return;
45        chart.BackgroundColor = value;
46      }
47    }
48
49    private IChart chart;
50    public IChart Chart {
51      get { return chart; }
52      protected set {
53        if (chart != null) DeregisterChartEvents(chart);
54        chart = value;
55        chart.Enabled = Enabled;
56        pictureBox.Enabled = Enabled;
57        if (chart != null) RegisterChartEvents(chart);
58      }
59    }
60
61    private ChartMode mode;
62    public ChartMode Mode {
63      get { return mode; }
64      set {
65        if (mode == value) return;
66        mode = value;
67        SetButtonCheckedSate();
68        SetPictureBoxCursor(GetPictureBoxCursor());
69        OnModeChanged();
70        if (chart != null) {
71          GenerateImage();
72        }
73      }
74    }
75
76    public bool ScaleOnResize { get; set; }
77
78    public bool IsRenderingPaused { get { return SuppressRender; } }
79
80    public ChartControl() : this(null) { }
81    public ChartControl(IChart defaultChart) {
82      InitializeComponent();
83      ScaleOnResize = true;
84      Chart = defaultChart ?? new Chart(0, 0, Width, Height);
85    }
86
87    public void AddChartModes(params ChartMode[] chartModes) {
88      foreach (var chartMode in chartModes)
89        Modes.Add(chartMode.GetType(), chartMode);
90
91      RebuildButtonPanel();
92    }
93
94    protected virtual void RebuildButtonPanel() {
95      buttonPanel.Controls.Clear();
96
97      int locationY = 3;
98      foreach (var chartMode in Modes.Values) {
99        var rb = CreateChartModeRadioButton(chartMode);
100        rb.Location = new Point(3, locationY);
101        toolTip.SetToolTip(rb, chartMode.ToolTip);
102        buttonPanel.Controls.Add(rb);
103        locationY += rb.Height + rb.Margin.Vertical;
104      }
105    }
106
107    public void SuspendRendering() {
108      SuppressRender = true;
109    }
110
111    public void ResumeRendering() {
112      SuppressRender = false;
113      if (Chart != null) GenerateImage();
114    }
115
116    protected virtual void SetButtonCheckedSate() {
117      foreach (var rb in buttonPanel.Controls.OfType<RadioButton>())
118        rb.Checked = rb.Tag == Mode;
119    }
120
121    protected virtual void SetPictureBoxCursor(Cursor cursor) {
122      if (pictureBox.Cursor != cursor) pictureBox.Cursor = cursor;
123    }
124
125    protected virtual Cursor GetPictureBoxCursor() {
126      if (mode == null) return null;
127
128      return mode.Cursor;
129    }
130
131    protected virtual void RegisterChartEvents(IChart chart) {
132      chart.RedrawRequired += ChartOnUpdateRequired;
133    }
134
135    protected virtual void DeregisterChartEvents(IChart chart) {
136      chart.RedrawRequired -= ChartOnUpdateRequired;
137    }
138
139    protected virtual void ChartOnUpdateRequired(object sender, EventArgs e) {
140      if (SuppressRender) return;
141      GenerateImage();
142    }
143
144    #region PictureBox Events
145    protected virtual void PictureBoxOnSizeChanged(object sender, EventArgs e) {
146      if (Chart == null) return;
147      if (ScaleOnResize) {
148        if ((pictureBox.Width > 0) && (pictureBox.Height > 0) && (Chart != null)) {
149          var point = Chart.TransformPixelToWorld(new Point(pictureBox.Width, Chart.SizeInPixels.Height - pictureBox.Height));
150          var diff = Chart.UpperRight - point;
151          Chart.SetPosition(new PointD(Chart.LowerLeft.X + (diff.DX / 2.0), Chart.LowerLeft.Y + (diff.DY / 2.0)),
152            new PointD(Chart.UpperRight.X - (diff.DX / 2.0), Chart.UpperRight.Y - (diff.DY / 2.0)));
153        }
154      }
155      GenerateImage();
156    }
157
158    protected virtual void PictureBoxOnVisibleChanged(object sender, EventArgs e) {
159      if (pictureBox.Visible && RenderingRequired) GenerateImage();
160    }
161
162    protected virtual void PictureBoxOnMouseClick(object sender, MouseEventArgs e) {
163      if (mode == null) return;
164      mode.HandleOnMouseClick(sender, e);
165    }
166
167    protected virtual void PictureBoxOnMouseDoubleClick(object sender, MouseEventArgs e) {
168      if (mode == null) return;
169      mode.HandleOnMouseDoubleClick(sender, e);
170    }
171
172    protected virtual void OnKeyDown(object sender, KeyEventArgs e) {
173      if (mode == null) return;
174      mode.HandleOnKeyDown(sender, e);
175    }
176
177    protected virtual void OnKeyUp(object sender, KeyEventArgs e) {
178      if (mode == null) return;
179      mode.HandleOnKeyUp(sender, e);
180    }
181
182    protected virtual void PictureBoxOnMouseWheel(object sender, MouseEventArgs e) {
183      if (mode == null) return;
184      mode.HandleOnMouseWheel(sender, e);
185    }
186
187    protected virtual void PictureBoxOnMouseDown(object sender, MouseEventArgs e) {
188      if (mode == null) return;
189      mode.HandleOnMouseDown(sender, e);
190    }
191
192    protected virtual void PictureBoxOnMouseUp(object sender, MouseEventArgs e) {
193      if (mode == null) return;
194      mode.HandleOnMouseUp(sender, e);
195
196      if (Chart == null) return;
197
198      if (e.Button == MouseButtons.Right) {
199        propertiesToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
200        oneLayerUpToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
201        oneLayerDownToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
202        intoForegroundToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
203        intoBackgroundToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
204      }
205    }
206
207    protected virtual void PictureBoxOnMouseMove(object sender, MouseEventArgs e) {
208      if (InvokeRequired) {
209        Invoke((Action<object, MouseEventArgs>)PictureBoxOnMouseMove, sender, e);
210      } else {
211        var toolTipText = Chart.GetToolTipText(e.Location);
212        if (toolTip.GetToolTip(pictureBox) != toolTipText) toolTip.SetToolTip(pictureBox, toolTipText);
213
214        if (mode == null) return;
215
216        mode.HandleOnMouseMove(sender, e);
217
218        SetPictureBoxCursor(mode.Cursor);
219      }
220    }
221
222    protected virtual void PictureBoxOnMouseEnter(object sender, EventArgs e) {
223      if (InvokeRequired) {
224        Invoke((Action<object, MouseEventArgs>)PictureBoxOnMouseEnter, sender, e);
225        return;
226      }
227      if (!Focused) this.pictureBox.Focus();
228
229      if (mode == null) return;
230
231      mode.HandleOnMouseEnter(sender, e);
232    }
233
234    protected virtual void PictureBoxOnMouseLeave(object sender, EventArgs e) {
235      if (mode == null) return;
236      mode.HandleOnMouseLeave(sender, e);
237    }
238
239    protected virtual void PictureBoxOnClick(object sender, EventArgs e) {
240      if (InvokeRequired) {
241        Invoke((Action<Object, MouseEventArgs>)PictureBoxOnClick, sender, e);
242        return;
243      }
244      if (!Focused) this.pictureBox.Focus();
245
246      if (mode == null) return;
247
248      mode.HandleOnClick(sender, e);
249    }
250    #endregion
251
252    protected virtual void PictureBoxContextMenuStripOnOpening(object sender, CancelEventArgs e) { }
253
254    protected virtual void oneLayerUpToolStripMenuItem_Click(object sender, EventArgs e) {
255      if (Chart == null) return;
256      if (Chart.Group.SelectedPrimitives.Count() == 1) {
257        Chart.OneLayerUp(Chart.Group.SelectedPrimitives.First());
258      }
259    }
260    protected virtual void oneLayerDownToolStripMenuItem_Click(object sender, EventArgs e) {
261      if (Chart == null) return;
262      if (Chart.Group.SelectedPrimitives.Count() == 1) {
263        Chart.OneLayerDown(Chart.Group.SelectedPrimitives.First());
264      }
265    }
266    protected virtual void intoForegroundToolStripMenuItem_Click(object sender, EventArgs e) {
267      if (Chart == null) return;
268      if (Chart.Group.SelectedPrimitives.Count() == 1) {
269        Chart.IntoForeground(Chart.Group.SelectedPrimitives.First());
270      }
271    }
272    protected virtual void intoBackgroundToolStripMenuItem_Click(object sender, EventArgs e) {
273      if (Chart == null) return;
274      if (Chart.Group.SelectedPrimitives.Count() == 1) {
275        Chart.IntoBackground(Chart.Group.SelectedPrimitives.First());
276      }
277    }
278    protected virtual void propertiesToolStripMenuItem_Click(object sender, EventArgs e) {
279      if (Chart == null) return;
280      if (Chart.Group.SelectedPrimitives.Count() == 1) {
281        using (var dialog = new PropertiesDialog(Chart.Group.SelectedPrimitives.First())) {
282          dialog.ShowDialog(this);
283        }
284      }
285    }
286    protected virtual void saveImageToolStripMenuItem_Click(object sender, EventArgs e) {
287      if (Picture == null) return;
288
289      if (saveFileDialog.ShowDialog() == DialogResult.OK) {
290        var format = ImageFormat.Bmp;
291        var filename = saveFileDialog.FileName.ToLower();
292        if (filename.EndsWith("emf")) {
293          using (var g1 = Graphics.FromImage(Picture)) {
294            var rectangle = new System.Drawing.Rectangle(0, 0, Picture.Width, Picture.Height);
295            using (var metafile = new Metafile(filename, g1.GetHdc(), rectangle, MetafileFrameUnit.Pixel, EmfType.EmfPlusDual))
296            using (var g2 = Graphics.FromImage(metafile))
297              Chart.Render(g2, pictureBox.Width, pictureBox.Height);
298          }
299        } else {
300          using (var graphics = Graphics.FromImage(Picture))
301            Chart.Render(graphics, Picture.Width, Picture.Height);
302
303          if (filename.EndsWith("jpg")) {
304            format = ImageFormat.Jpeg;
305          } else if (filename.EndsWith("gif")) {
306            format = ImageFormat.Gif;
307          } else if (filename.EndsWith("png")) {
308            format = ImageFormat.Png;
309          } else if (filename.EndsWith("tif")) {
310            format = ImageFormat.Tiff;
311          }
312
313          Picture.Save(saveFileDialog.FileName, format);
314        }
315      }
316    }
317
318    protected virtual void GenerateImage() {
319      if (InvokeRequired) {
320        Invoke((Action)GenerateImage);
321        return;
322      }
323      if (!Visible) {
324        RenderingRequired = true;
325      } else {
326        if ((pictureBox.Width == 0) || (pictureBox.Height == 0)) {
327          pictureBox.Image = pictureBox.ErrorImage;
328          if (Picture != null) Picture.Dispose();
329          Picture = null;
330        } else {
331          if (Picture != null) Picture.Dispose();
332          Picture = new Bitmap(pictureBox.Width, pictureBox.Height);
333          using (var graphics = Graphics.FromImage(Picture)) {
334            graphics.SetClip(new System.Drawing.Rectangle(0, 0, pictureBox.Width, pictureBox.Height));
335            Chart.Render(graphics, pictureBox.Width, pictureBox.Height);
336          }
337        }
338        pictureBox.Image = Picture;
339        RenderingRequired = false;
340      }
341    }
342
343    public event EventHandler ModeChanged;
344    protected void OnModeChanged() {
345      var handler = ModeChanged;
346      if (handler != null) handler(this, EventArgs.Empty);
347    }
348
349    private void ChartControl_Load(object sender, EventArgs e) {
350      if (!SuppressRender) GenerateImage();
351    }
352
353    #region Helpers
354    private RadioButton CreateChartModeRadioButton(ChartMode chartMode) {
355      var rb = new RadioButton {
356        Appearance = Appearance.Button,
357        Image = chartMode.Image,
358        Size = new Size(24, 24),
359        TabStop = true,
360        Tag = chartMode,
361        UseVisualStyleBackColor = true
362      };
363
364      rb.CheckedChanged += (sender, args) => { if (rb.Checked) Mode = chartMode; };
365
366      return rb;
367    }
368    #endregion
369  }
370}
Note: See TracBrowser for help on using the repository browser.