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

Last change on this file since 13115 was 13115, checked in by jkarder, 4 years ago

#1265: worked on visualization

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