Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/ImageExportDialog.cs @ 9496

Last change on this file since 9496 was 9496, checked in by abeham, 11 years ago

#2054:

  • Added check boxes to hide or show a certain axis
  • Fixed tab order
  • Changed some of the default values
  • Improved layout of controls
  • Clear title if the text is set to empty
  • Added tooltips to most controls
File size: 16.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 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.ComponentModel;
24using System.Drawing;
25using System.Drawing.Imaging;
26using System.IO;
27using System.Linq;
28using System.Windows.Forms;
29using System.Windows.Forms.DataVisualization.Charting;
30
31namespace HeuristicLab.Visualization.ChartControlsExtensions {
32  public sealed partial class ImageExportDialog : Form {
33    private const float CMPERINCH = 2.54f;
34    private static readonly string DPI = "dpi", DPCM = "dpcm", INCH = "inch", CM = "cm";
35    private Chart originalChart, workingChart;
36    private bool SuppressEvents { get; set; }
37
38    /// <summary>
39    /// Initializes a new ImageExportDialog.
40    /// </summary>
41    /// <remarks>
42    /// Throws an ArgumentNullException if <paramref name="chart"/> is null.
43    /// </remarks>
44    /// <param name="chart">The chart for which the export should be generated.</param>
45    public ImageExportDialog(Chart chart) {
46      if (chart == null) throw new ArgumentNullException("chart");
47      this.originalChart = chart;
48      InitializeComponent();
49      #region Custom Initialization
50      SuppressEvents = true;
51      try {
52        resolutionUnitComboBox.Items.Add(DPI);
53        resolutionUnitComboBox.Items.Add(DPCM);
54        lengthUnitComboBox.Items.Add(INCH);
55        lengthUnitComboBox.Items.Add(CM);
56        resolutionUnitComboBox.SelectedIndex = 0;
57        if (System.Globalization.RegionInfo.CurrentRegion.IsMetric)
58          lengthUnitComboBox.SelectedIndex = 1;
59        else lengthUnitComboBox.SelectedIndex = 0;
60
61        titleFontSizeComboBox.Text = "10";
62        axisFontSizeComboBox.Text = "8";
63        scalesFontSizeComboBox.Text = "6";
64        legendFontSizeComboBox.Text = "6";
65        resolutionComboBox.Text = "150";
66        SuppressEvents = false;
67        splitContainer.Panel2Collapsed = true;
68        Width = 305;
69        Height = 560;
70      } finally { SuppressEvents = false; }
71      #endregion
72    }
73
74    private void UpdateFields() {
75      var area = GetCurrentChartArea();
76
77      try {
78        SuppressEvents = true;
79
80        if (workingChart.Titles.Count == 0) titleFontSizeComboBox.Text = "10";
81        else {
82          titleTextBox.Text = workingChart.Titles[0].Text;
83          titleFontSizeComboBox.Text = workingChart.Titles[0].Font.SizeInPoints.ToString();
84        }
85
86        primaryXTextBox.Text = area.AxisX.Title;
87        primaryYTextBox.Text = area.AxisY.Title;
88        secondaryXTextBox.Text = area.AxisX2.Title;
89        secondaryYTextBox.Text = area.AxisY2.Title;
90
91        axisFontSizeComboBox.Text = area.AxisX.TitleFont.SizeInPoints.ToString();
92        scalesFontSizeComboBox.Text = area.AxisX.LabelStyle.Font.SizeInPoints.ToString();
93        if (workingChart.Legends.Count == 0) legendFontSizeComboBox.Text = "6";
94        else legendFontSizeComboBox.Text = workingChart.Legends[0].Font.SizeInPoints.ToString();
95      } finally {
96        SuppressEvents = false;
97      }
98    }
99
100    private ChartArea GetCurrentChartArea() {
101      return workingChart.ChartAreas[chartAreaComboBox.Text];
102    }
103
104    private void UpdatePreview() {
105      float dpi;
106      float width;
107      float height;
108      GetImageParameters(out dpi, out width, out height);
109
110      if (previewPictureBox.Image != null) {
111        previewPictureBox.Image.Dispose();
112        previewPictureBox.Image = null;
113      }
114
115      int previewWidth, previewHeight;
116      if (width / height >= 1.0) {
117        previewWidth = previewPictureBox.Width;
118        previewHeight = (int)Math.Round(height / width * previewWidth);
119      } else {
120        previewHeight = previewPictureBox.Height;
121        previewWidth = (int)Math.Round(width / height * previewHeight);
122      }
123
124      var scaleFactor = (float)Math.Min(previewWidth / width, previewHeight / height);
125      if (scaleFactor >= 1) {
126        previewZoomLabel.Text = "100%";
127        previewWidth = (int)Math.Round(width);
128        previewHeight = (int)Math.Round(height);
129      } else previewZoomLabel.Text = (scaleFactor * 100).ToString("0") + "%";
130      rawImageSizeLabel.Text = GetRawImageSizeInMegabytes(width, height).ToString("0.00") + "M   " + "(" + Math.Round(width).ToString("0") + " x " + Math.Round(height).ToString("0") + ") pixels";
131
132      var image = new Bitmap(previewWidth, previewHeight);
133      image.SetResolution(dpi, dpi);
134      using (Graphics graphics = Graphics.FromImage(image)) {
135        if (scaleFactor < 1) graphics.ScaleTransform(scaleFactor, scaleFactor);
136        workingChart.Printing.PrintPaint(graphics, new Rectangle(0, 0, (int)Math.Round(width), (int)Math.Round(height)));
137      }
138      previewPictureBox.Image = image;
139    }
140
141    private void GetImageParameters(out float dpi, out float width, out float height) {
142      dpi = float.Parse(resolutionComboBox.Text);
143      if (resolutionUnitComboBox.Text == DPCM) dpi *= CMPERINCH;
144      width = (float)widthNumericUD.Value;
145      height = (float)heightNumericUD.Value;
146      if (lengthUnitComboBox.Text == CM) {
147        width /= CMPERINCH; height /= CMPERINCH;
148      }
149      width *= dpi; height *= dpi;
150    }
151
152    protected override void OnShown(EventArgs e) {
153      #region Create copy of chart
154      var prevContent = originalChart.Serializer.Content;
155      var prevFormat = originalChart.Serializer.Format;
156      originalChart.Serializer.Content = SerializationContents.Default;
157      originalChart.Serializer.Format = SerializationFormat.Binary;
158      var ms = new MemoryStream();
159      originalChart.Serializer.Save(ms);
160
161      ms.Seek(0, SeekOrigin.Begin);
162      workingChart = new EnhancedChart();
163      workingChart.Serializer.Format = originalChart.Serializer.Format;
164      workingChart.Serializer.Load(ms);
165      ms.Close();
166
167      originalChart.Serializer.Content = prevContent;
168      originalChart.Serializer.Format = prevFormat;
169      #endregion
170
171      chartAreaComboBox.Items.Clear();
172      foreach (var area in originalChart.ChartAreas) {
173        chartAreaComboBox.Items.Add(area.Name);
174      }
175      chartAreaComboBox.SelectedIndex = 0;
176      SuppressEvents = true;
177      try {
178        showPrimaryXAxisCheckBox.Checked = originalChart.Series.Any(x => x.XAxisType == AxisType.Primary);
179        showPrimaryYAxisCheckBox.Checked = originalChart.Series.Any(x => x.YAxisType == AxisType.Primary);
180        showSecondaryXAxisCheckBox.Checked = originalChart.Series.Any(x => x.XAxisType == AxisType.Secondary);
181        showSecondaryYAxisCheckBox.Checked = originalChart.Series.Any(x => x.YAxisType == AxisType.Secondary);
182      } finally { SuppressEvents = false; }
183      base.OnShown(e);
184
185      if (togglePreviewCheckBox.Checked) UpdatePreview();
186    }
187
188    private void togglePreviewCheckBox_CheckedChanged(object sender, EventArgs e) {
189      splitContainer.Panel2Collapsed = !togglePreviewCheckBox.Checked;
190      togglePreviewCheckBox.Text = togglePreviewCheckBox.Checked ? "<" : ">";
191      if (splitContainer.Panel2Collapsed)
192        Width = cancelButton.Right + cancelButton.Margin.Right + Margin.Right + 10;
193      else
194        Width = splitContainer.Right + splitContainer.Margin.Right + Margin.Right;
195      if (togglePreviewCheckBox.Checked) UpdatePreview();
196    }
197
198    private void chartAreaComboBox_SelectedIndexChanged(object sender, EventArgs e) {
199      if (chartAreaComboBox.SelectedIndex >= 0)
200        UpdateFields();
201    }
202
203    private void titleTextBox_TextChanged(object sender, EventArgs e) {
204      if (!SuppressEvents) {
205        if (string.IsNullOrEmpty(titleTextBox.Text))
206          workingChart.Titles.Clear();
207        else {
208          if (workingChart.Titles.Count > 0) {
209            workingChart.Titles[0].Text = titleTextBox.Text;
210          } else {
211            var t = new Title(titleTextBox.Text);
212            t.Font = ChangeFontSizePt(t.Font, float.Parse(titleFontSizeComboBox.Text));
213            workingChart.Titles.Add(t);
214          }
215        }
216        if (togglePreviewCheckBox.Checked) UpdatePreview();
217      }
218    }
219
220    private void primaryXTextBox_TextChanged(object sender, EventArgs e) {
221      if (!SuppressEvents) {
222        var area = GetCurrentChartArea();
223        area.AxisX.Title = primaryXTextBox.Text;
224        if (togglePreviewCheckBox.Checked) UpdatePreview();
225      }
226    }
227
228    private void primaryYTextBox_TextChanged(object sender, EventArgs e) {
229      if (!SuppressEvents) {
230        var area = GetCurrentChartArea();
231        area.AxisY.Title = primaryYTextBox.Text;
232        if (togglePreviewCheckBox.Checked) UpdatePreview();
233      }
234    }
235
236    private void secondaryXTextBox_TextChanged(object sender, EventArgs e) {
237      if (!SuppressEvents) {
238        var area = GetCurrentChartArea();
239        area.AxisX2.Title = secondaryXTextBox.Text;
240        if (togglePreviewCheckBox.Checked) UpdatePreview();
241      }
242    }
243
244    private void secondaryYTextBox_TextChanged(object sender, EventArgs e) {
245      if (!SuppressEvents) {
246        var area = GetCurrentChartArea();
247        area.AxisY2.Title = secondaryYTextBox.Text;
248        if (togglePreviewCheckBox.Checked) UpdatePreview();
249      }
250    }
251
252    private void showPrimaryXAxisCheckBox_CheckedChanged(object sender, EventArgs e) {
253      if (!SuppressEvents) {
254        var area = GetCurrentChartArea();
255        var isChecked = ((CheckBox)sender).Checked;
256        area.AxisX.Enabled = isChecked ? AxisEnabled.True : AxisEnabled.False;
257        if (togglePreviewCheckBox.Checked) UpdatePreview();
258      }
259    }
260
261    private void showPrimaryYAxisCheckBox_CheckedChanged(object sender, EventArgs e) {
262      if (!SuppressEvents) {
263        var area = GetCurrentChartArea();
264        var isChecked = ((CheckBox)sender).Checked;
265        area.AxisY.Enabled = isChecked ? AxisEnabled.True : AxisEnabled.False;
266        if (togglePreviewCheckBox.Checked) UpdatePreview();
267      }
268    }
269
270    private void showSecondaryXAxisCheckBox_CheckedChanged(object sender, EventArgs e) {
271      if (!SuppressEvents) {
272        var area = GetCurrentChartArea();
273        var isChecked = ((CheckBox)sender).Checked;
274        area.AxisX2.Enabled = isChecked ? AxisEnabled.True : AxisEnabled.False;
275        if (togglePreviewCheckBox.Checked) UpdatePreview();
276      }
277    }
278
279    private void showSecondaryYAxisCheckBox_CheckedChanged(object sender, EventArgs e) {
280      if (!SuppressEvents) {
281        var area = GetCurrentChartArea();
282        var isChecked = ((CheckBox)sender).Checked;
283        area.AxisY2.Enabled = isChecked ? AxisEnabled.True : AxisEnabled.False;
284        if (togglePreviewCheckBox.Checked) UpdatePreview();
285      }
286    }
287
288    private void widthNumericUD_ValueChanged(object sender, EventArgs e) {
289      float dpi, width, height;
290      GetImageParameters(out dpi, out width, out height);
291      if (GetRawImageSizeInMegabytes(width, height) > 25) // bigger than A4 at 300dpi
292        MessageBox.Show("Warning: The image is getting quite big.");
293      if (togglePreviewCheckBox.Checked) UpdatePreview();
294    }
295
296    private void heightNumericUD_ValueChanged(object sender, EventArgs e) {
297      float dpi, width, height;
298      GetImageParameters(out dpi, out width, out height);
299      if (GetRawImageSizeInMegabytes(width, height) > 25) // bigger than A4 at 300dpi
300        MessageBox.Show("Warning: The image is getting quite big.");
301      if (togglePreviewCheckBox.Checked) UpdatePreview();
302    }
303
304    private void titleFontSizeComboBox_TextChanged(object sender, EventArgs e) {
305      if (!SuppressEvents) {
306        float fontSize;
307        if (float.TryParse(titleFontSizeComboBox.Text, out fontSize)) {
308          if (workingChart.Titles.Count > 0) {
309            workingChart.Titles[0].Font = ChangeFontSizePt(workingChart.Titles[0].Font, fontSize);
310            if (togglePreviewCheckBox.Checked) UpdatePreview();
311          }
312        }
313      }
314    }
315
316    private void axisFontSizeComboBox_TextChanged(object sender, EventArgs e) {
317      if (!SuppressEvents) {
318        float fontSize;
319        if (float.TryParse(axisFontSizeComboBox.Text, out fontSize)) {
320          var area = GetCurrentChartArea();
321          foreach (Axis a in area.Axes)
322            a.TitleFont = ChangeFontSizePt(a.TitleFont, fontSize);
323        }
324        if (togglePreviewCheckBox.Checked) UpdatePreview();
325      }
326    }
327
328    private void scalesFontSizeComboBox_TextChanged(object sender, EventArgs e) {
329      if (!SuppressEvents) {
330        float fontSize;
331        if (float.TryParse(scalesFontSizeComboBox.Text, out fontSize)) {
332          var area = GetCurrentChartArea();
333          foreach (var a in area.Axes)
334            a.LabelStyle.Font = ChangeFontSizePt(a.LabelStyle.Font, fontSize);
335        }
336        if (togglePreviewCheckBox.Checked) UpdatePreview();
337      }
338    }
339
340    private void legendFontSizeComboBox_TextChanged(object sender, EventArgs e) {
341      if (!SuppressEvents) {
342        float fontSize;
343        if (float.TryParse(legendFontSizeComboBox.Text, out fontSize)) {
344          foreach (var l in workingChart.Legends)
345            l.Font = ChangeFontSizePt(l.Font, fontSize);
346        }
347        if (togglePreviewCheckBox.Checked) UpdatePreview();
348      }
349    }
350
351    private void numericComboBox_Validating(object sender, CancelEventArgs e) {
352      if (!(sender is ComboBox)) return;
353      float number;
354      e.Cancel = !float.TryParse((sender as ComboBox).Text, out number);
355    }
356
357    private void resolutionComboBox_TextChanged(object sender, EventArgs e) {
358      float resolution;
359      if (float.TryParse(resolutionComboBox.Text, out resolution)) {
360        if (togglePreviewCheckBox.Checked) UpdatePreview();
361      }
362    }
363
364    private void resolutionComboBox_Validating(object sender, CancelEventArgs e) {
365      float resolution;
366      e.Cancel = !float.TryParse(resolutionComboBox.Text, out resolution);
367    }
368
369    private void resolutionUnitComboBox_SelectedIndexChanged(object sender, EventArgs e) {
370      if (togglePreviewCheckBox.Checked) UpdatePreview();
371    }
372
373    private void lengthUnitComboBox_SelectedIndexChanged(object sender, EventArgs e) {
374      if (togglePreviewCheckBox.Checked) UpdatePreview();
375    }
376
377    private void okButton_Click(object sender, EventArgs e) {
378      float dpi;
379      float width;
380      float height;
381      GetImageParameters(out dpi, out width, out height);
382
383      var image = new Bitmap((int)Math.Round(width), (int)Math.Round(height));
384      image.SetResolution(dpi, dpi);
385      using (var graphics = Graphics.FromImage(image)) {
386        workingChart.Printing.PrintPaint(graphics, new Rectangle(0, 0, image.Width, image.Height));
387      }
388
389      if (titleTextBox.Text.Trim() != String.Empty) saveFileDialog.FileName = titleTextBox.Text.Trim();
390      if (saveFileDialog.ShowDialog() == DialogResult.OK) {
391        var format = ImageFormat.Bmp;
392        var filename = saveFileDialog.FileName.ToLower();
393        if (filename.EndsWith("jpg")) {
394          format = ImageFormat.Jpeg;
395        } else if (filename.EndsWith("emf")) {
396          format = ImageFormat.Emf;
397        } else if (filename.EndsWith("gif")) {
398          format = ImageFormat.Gif;
399        } else if (filename.EndsWith("png")) {
400          format = ImageFormat.Png;
401        } else if (filename.EndsWith("tif")) {
402          format = ImageFormat.Tiff;
403        }
404        image.Save(saveFileDialog.FileName, format);
405      }
406
407      image.Dispose();
408
409      Cleanup();
410    }
411
412    private void cancelButton_Click(object sender, EventArgs e) {
413      Cleanup();
414    }
415
416    private void Cleanup() {
417      if (previewPictureBox.Image != null) previewPictureBox.Image.Dispose();
418      previewPictureBox.Image = null;
419      workingChart = null;
420    }
421
422    private static Font ChangeFontSizePt(Font font, float fontSize) {
423      if (font != null) {
424        float currentSize = font.Size;
425        if (currentSize != fontSize) {
426          font = new Font(font.Name, fontSize, font.Style, GraphicsUnit.Point, font.GdiCharSet, font.GdiVerticalFont);
427        }
428      }
429      return font;
430    }
431
432    private static float GetRawImageSizeInMegabytes(float width, float height) {
433      return ((3 * width * height) / (1024 * 1024));
434    }
435
436  }
437}
Note: See TracBrowser for help on using the repository browser.