Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 13822 was 13822, checked in by bburlacu, 8 years ago

#1265: Removed C# 4.6 language features from ChartControl.cs (default property value) to fix compilation.

File size: 15.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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.Drawing2D;
27using System.Drawing.Imaging;
28using System.Linq;
29using System.Windows.Forms;
30
31namespace HeuristicLab.Visualization {
32  public partial class ChartControl : UserControl {
33    protected Bitmap Picture;
34    protected bool RenderingRequired;
35    protected Dictionary<Type, ChartMode> Modes = new Dictionary<Type, ChartMode>();
36    protected Stack<ChartMode> ModeStack = new Stack<ChartMode>();
37    protected List<ChartMode.Shortcut> Shortcuts = new List<ChartMode.Shortcut>();
38    protected ChartMode.Shortcut ActiveShortcut;
39
40    protected bool SuppressEvents { get; set; }
41    private bool SuppressRender { get; set; }
42
43    public bool ShowToolBar {
44      get { return !splitContainer.Panel1Collapsed; }
45      set { splitContainer.Panel1Collapsed = !value; }
46    }
47
48    private IChart chart;
49    public IChart Chart {
50      get { return chart; }
51      protected set {
52        if (chart != null) DeregisterChartEvents(chart);
53        chart = value;
54        chart.Enabled = Enabled;
55        pictureBox.Enabled = Enabled;
56        if (chart != null) RegisterChartEvents(chart);
57      }
58    }
59
60    private ChartMode mode;
61    private ChartMode defaultMode;
62    public ChartMode Mode {
63      get { return mode; }
64      set {
65        if (mode == value) return;
66        mode = value;
67        if (defaultMode == null) defaultMode = mode;
68        if (mode == null) mode = defaultMode;
69        SetModeButtonCheckedState();
70        SetModeMenuItemCheckedState();
71        SetPictureBoxCursor(GetPictureBoxCursor());
72        OnModeChanged();
73        if (chart != null) {
74          GenerateImage();
75        }
76      }
77    }
78
79    public SmoothingMode SmoothingMode { get; set; }
80
81    public bool ScaleOnResize { get; set; }
82
83    public bool IsRenderingPaused { get { return SuppressRender; } }
84
85    public ChartControl() : this(null) { }
86    public ChartControl(IChart defaultChart) {
87      InitializeComponent();
88      ScaleOnResize = true;
89      Chart = defaultChart ?? new Chart(0, 0, Width, Height);
90    }
91
92    public void AddChartModes(params ChartMode[] chartModes) {
93      foreach (var chartMode in chartModes) {
94        Modes.Add(chartMode.GetType(), chartMode);
95        foreach (var shortcut in chartMode.Shortcuts)
96          Shortcuts.Add(shortcut);
97      }
98
99      ReloadModeToolBar();
100      ReloadModeContextMenu();
101    }
102
103    public void SetTempChartMode(ChartMode chartMode) {
104      if (Mode == chartMode) return;
105
106      ModeStack.Push(mode);
107      Mode = chartMode;
108    }
109
110    public void ResetTempChartMode() {
111      if (ModeStack.Any())
112        Mode = ModeStack.Pop();
113    }
114
115    public void SuspendRendering() {
116      SuppressRender = true;
117    }
118
119    public void ResumeRendering() {
120      SuppressRender = false;
121      if (Chart != null) GenerateImage();
122    }
123
124    public void RefreshPicture() {
125      pictureBox.Refresh();
126    }
127
128    public void UpdatePicture() {
129      pictureBox.Update();
130    }
131
132    public Graphics CreatePictureGraphics() {
133      return pictureBox.CreateGraphics();
134    }
135
136    protected virtual void ReloadModeToolBar() {
137      splitContainer.Panel1.Controls.Clear();
138
139      var chartModes = Modes.Values.ToList();
140      for (int i = 0; i < chartModes.Count; i++) {
141        var chartMode = chartModes[i];
142        var rb = CreateChartModeRadioButton(chartMode);
143        rb.Location = new Point(3, 3 + i * (rb.Height + rb.Margin.Vertical));
144        rb.TabIndex = i;
145        toolTip.SetToolTip(rb, chartMode.ToolTipText);
146        splitContainer.Panel1.Controls.Add(rb);
147      }
148
149      SetModeButtonCheckedState();
150    }
151
152    protected virtual void ReloadModeContextMenu() {
153      modeToolStripMenuItem.DropDownItems.Clear();
154
155      foreach (var chartMode in Modes.Values) {
156        var mi = CreateChartModeMenuItem(chartMode);
157        modeToolStripMenuItem.DropDownItems.Add(mi);
158      }
159
160      SetModeMenuItemCheckedState();
161    }
162
163    protected virtual void SetModeButtonCheckedState() {
164      foreach (var rb in splitContainer.Panel1.Controls.OfType<RadioButton>())
165        rb.Checked = rb.Tag == Mode;
166    }
167
168    protected virtual void SetModeMenuItemCheckedState() {
169      foreach (var mi in modeToolStripMenuItem.DropDownItems.OfType<ToolStripMenuItem>())
170        mi.Checked = mi.Tag == Mode;
171    }
172
173    protected virtual void SetPictureBoxCursor(Cursor cursor) {
174      if (pictureBox.Cursor != cursor) pictureBox.Cursor = cursor;
175    }
176
177    protected virtual Cursor GetPictureBoxCursor() {
178      return mode != null ? mode.Cursor : null;
179    }
180
181    protected virtual void RegisterChartEvents(IChart chart) {
182      chart.RedrawRequired += ChartOnUpdateRequired;
183    }
184
185    protected virtual void DeregisterChartEvents(IChart chart) {
186      chart.RedrawRequired -= ChartOnUpdateRequired;
187    }
188
189    protected virtual void ChartOnUpdateRequired(object sender, EventArgs e) {
190      if (SuppressRender) return;
191      GenerateImage();
192    }
193
194    #region PictureBox Events
195    protected virtual void PictureBoxOnSizeChanged(object sender, EventArgs e) {
196      if (Chart == null) return;
197      if (ScaleOnResize) {
198        if ((pictureBox.Width > 0) && (pictureBox.Height > 0) && (Chart != null)) {
199          var point = Chart.TransformPixelToWorld(new Point(pictureBox.Width, Chart.SizeInPixels.Height - pictureBox.Height));
200          var diff = Chart.UpperRight - point;
201          Chart.SetPosition(new PointD(Chart.LowerLeft.X + (diff.DX / 2.0), Chart.LowerLeft.Y + (diff.DY / 2.0)),
202            new PointD(Chart.UpperRight.X - (diff.DX / 2.0), Chart.UpperRight.Y - (diff.DY / 2.0)));
203        }
204      }
205      GenerateImage();
206    }
207
208    protected virtual void PictureBoxOnVisibleChanged(object sender, EventArgs e) {
209      if (pictureBox.Visible && RenderingRequired) GenerateImage();
210    }
211
212    protected virtual void PictureBoxOnMouseClick(object sender, MouseEventArgs e) {
213      if (mode != null)
214        mode.HandleOnMouseClick(sender, e);
215    }
216
217    protected virtual void PictureBoxOnMouseDoubleClick(object sender, MouseEventArgs e) {
218      if (mode != null)
219        mode.HandleOnMouseDoubleClick(sender, e);
220    }
221
222    protected virtual void OnKeyDown(object sender, KeyEventArgs e) {
223      if (mode != null) {
224        mode.HandleOnKeyDown(sender, e);
225
226        if (e.Handled || ActiveShortcut != null) return;
227
228        foreach (var shortcut in Shortcuts) {
229          if (e.KeyCode == shortcut.Key && e.Modifiers == shortcut.Modifiers) {
230            ActiveShortcut = shortcut;
231            var downAction = shortcut.DownAction;
232            if (downAction != null) downAction();
233            e.Handled = true;
234            break;
235          }
236        }
237      }
238    }
239
240    protected virtual void OnKeyUp(object sender, KeyEventArgs e) {
241      if (mode != null) {
242        mode.HandleOnKeyUp(sender, e);
243
244        if (e.Handled || ActiveShortcut == null) return;
245
246        var modifiers = new List<Keys>(from key in Enum.GetValues(typeof(Keys)).Cast<Keys>()
247                                       where e.Modifiers.HasFlag(key)
248                                       select key);
249
250        if (ActiveShortcut.Key == e.KeyCode || ActiveShortcut.GetModifiers().Except(modifiers).Any()) {
251          var upAction = ActiveShortcut.UpAction;
252          if (upAction != null) upAction();
253          ActiveShortcut = null;
254          e.Handled = true;
255        }
256      }
257    }
258
259    protected virtual void PictureBoxOnMouseWheel(object sender, MouseEventArgs e) {
260      if (mode != null)
261        mode.HandleOnMouseWheel(sender, e);
262    }
263
264    protected virtual void PictureBoxOnMouseDown(object sender, MouseEventArgs e) {
265      if (mode != null)
266        mode.HandleOnMouseDown(sender, e);
267    }
268
269    protected virtual void PictureBoxOnMouseUp(object sender, MouseEventArgs e) {
270      if (mode != null)
271        mode.HandleOnMouseUp(sender, e);
272
273      if (Chart == null) return;
274
275      if (e.Button == MouseButtons.Right) {
276        propertiesToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
277        oneLayerUpToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
278        oneLayerDownToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
279        intoForegroundToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
280        intoBackgroundToolStripMenuItem.Enabled = Chart.Group.SelectedPrimitives.Count() == 1;
281      }
282    }
283
284    protected virtual void PictureBoxOnMouseMove(object sender, MouseEventArgs e) {
285      if (InvokeRequired) {
286        Invoke((Action<object, MouseEventArgs>)PictureBoxOnMouseMove, sender, e);
287      } else {
288        var toolTipText = Chart.GetToolTipText(e.Location);
289        if (toolTip.GetToolTip(pictureBox) != toolTipText) toolTip.SetToolTip(pictureBox, toolTipText);
290
291        if (mode != null)
292          mode.HandleOnMouseMove(sender, e);
293
294        SetPictureBoxCursor(GetPictureBoxCursor());
295      }
296    }
297
298    protected virtual void PictureBoxOnMouseEnter(object sender, EventArgs e) {
299      if (InvokeRequired) {
300        Invoke((Action<object, MouseEventArgs>)PictureBoxOnMouseEnter, sender, e);
301        return;
302      }
303      if (!Focused) pictureBox.Focus();
304
305      if (mode != null)
306        mode.HandleOnMouseEnter(sender, e);
307    }
308
309    protected virtual void PictureBoxOnMouseLeave(object sender, EventArgs e) {
310      if (mode != null)
311        mode.HandleOnMouseLeave(sender, e);
312    }
313
314    protected virtual void PictureBoxOnClick(object sender, EventArgs e) {
315      if (InvokeRequired) {
316        Invoke((Action<object, MouseEventArgs>)PictureBoxOnClick, sender, e);
317        return;
318      }
319      if (!Focused) pictureBox.Focus();
320
321      if (mode != null)
322        mode.HandleOnClick(sender, e);
323    }
324    #endregion
325
326    protected virtual void PictureBoxContextMenuStripOnOpening(object sender, CancelEventArgs e) { }
327
328    protected virtual void oneLayerUpToolStripMenuItem_Click(object sender, EventArgs e) {
329      if (Chart == null) return;
330      if (Chart.Group.SelectedPrimitives.Count() == 1) {
331        Chart.OneLayerUp(Chart.Group.SelectedPrimitives.First());
332      }
333    }
334    protected virtual void oneLayerDownToolStripMenuItem_Click(object sender, EventArgs e) {
335      if (Chart == null) return;
336      if (Chart.Group.SelectedPrimitives.Count() == 1) {
337        Chart.OneLayerDown(Chart.Group.SelectedPrimitives.First());
338      }
339    }
340    protected virtual void intoForegroundToolStripMenuItem_Click(object sender, EventArgs e) {
341      if (Chart == null) return;
342      if (Chart.Group.SelectedPrimitives.Count() == 1) {
343        Chart.IntoForeground(Chart.Group.SelectedPrimitives.First());
344      }
345    }
346    protected virtual void intoBackgroundToolStripMenuItem_Click(object sender, EventArgs e) {
347      if (Chart == null) return;
348      if (Chart.Group.SelectedPrimitives.Count() == 1) {
349        Chart.IntoBackground(Chart.Group.SelectedPrimitives.First());
350      }
351    }
352    protected virtual void propertiesToolStripMenuItem_Click(object sender, EventArgs e) {
353      if (Chart == null) return;
354      if (Chart.Group.SelectedPrimitives.Count() == 1) {
355        using (var dialog = new PropertiesDialog(Chart.Group.SelectedPrimitives.First())) {
356          dialog.ShowDialog(this);
357        }
358      }
359    }
360    protected virtual void saveImageToolStripMenuItem_Click(object sender, EventArgs e) {
361      if (Picture == null) return;
362
363      if (saveFileDialog.ShowDialog() == DialogResult.OK) {
364        var format = ImageFormat.Bmp;
365        var filename = saveFileDialog.FileName.ToLower();
366        if (filename.EndsWith("emf")) {
367          using (var g1 = Graphics.FromImage(Picture)) {
368            var rectangle = new System.Drawing.Rectangle(0, 0, Picture.Width, Picture.Height);
369            using (var metafile = new Metafile(filename, g1.GetHdc(), rectangle, MetafileFrameUnit.Pixel, EmfType.EmfPlusDual))
370            using (var g2 = Graphics.FromImage(metafile))
371              Chart.Render(g2, pictureBox.Width, pictureBox.Height);
372          }
373        } else {
374          using (var graphics = Graphics.FromImage(Picture))
375            Chart.Render(graphics, Picture.Width, Picture.Height);
376
377          if (filename.EndsWith("jpg")) {
378            format = ImageFormat.Jpeg;
379          } else if (filename.EndsWith("gif")) {
380            format = ImageFormat.Gif;
381          } else if (filename.EndsWith("png")) {
382            format = ImageFormat.Png;
383          } else if (filename.EndsWith("tif")) {
384            format = ImageFormat.Tiff;
385          }
386
387          Picture.Save(saveFileDialog.FileName, format);
388        }
389      }
390    }
391
392    protected virtual void GenerateImage() {
393      if (InvokeRequired) {
394        Invoke((Action)GenerateImage);
395        return;
396      }
397      if (!Visible) {
398        RenderingRequired = true;
399      } else {
400        if ((pictureBox.Width == 0) || (pictureBox.Height == 0)) {
401          pictureBox.Image = pictureBox.ErrorImage;
402          if (Picture != null) Picture.Dispose();
403          Picture = null;
404        } else {
405          if (Picture != null) Picture.Dispose();
406          Picture = new Bitmap(pictureBox.Width, pictureBox.Height);
407          using (var graphics = Graphics.FromImage(Picture)) {
408            graphics.SmoothingMode = SmoothingMode;
409            graphics.SetClip(new System.Drawing.Rectangle(0, 0, pictureBox.Width, pictureBox.Height));
410            Chart.Render(graphics, pictureBox.Width, pictureBox.Height);
411          }
412        }
413        pictureBox.Image = Picture;
414        RenderingRequired = false;
415      }
416    }
417
418    public event EventHandler ModeChanged;
419    protected void OnModeChanged() {
420      var handler = ModeChanged;
421      if (handler != null) handler(this, EventArgs.Empty);
422    }
423
424    private void ChartControl_Load(object sender, EventArgs e) {
425      if (!SuppressRender) GenerateImage();
426    }
427
428    #region Helpers
429    private RadioButton CreateChartModeRadioButton(ChartMode chartMode) {
430      var rb = new RadioButton {
431        Appearance = Appearance.Button,
432        Image = chartMode.Image,
433        Size = new Size(24, 24),
434        TabStop = true,
435        Tag = chartMode,
436        UseVisualStyleBackColor = true
437      };
438
439      rb.CheckedChanged += (sender, args) => { if (rb.Checked) chartMode.Select(); };
440
441      return rb;
442    }
443
444    private ToolStripMenuItem CreateChartModeMenuItem(ChartMode chartMode) {
445      var mi = new ToolStripMenuItem(chartMode.Text) {
446        CheckOnClick = true,
447        Image = chartMode.Image,
448        Tag = chartMode
449      };
450
451      mi.CheckedChanged += (sender, args) => { if (mi.Checked) chartMode.Select(); };
452
453      return mi;
454    }
455    #endregion
456  }
457}
Note: See TracBrowser for help on using the repository browser.