Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 13076 was 13076, checked in by jkarder, 8 years ago

#1265: implemented new chart mode concept

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