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

Last change on this file since 13132 was 13132, checked in by jkarder, 7 years ago

#1265: worked on visualization

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