Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Optimization.Views/3.3/RunCollectionBubbleChartView.cs @ 4652

Last change on this file since 4652 was 4652, checked in by mkommend, 13 years ago

Added statistical information to the RunCollectionBoxPlotView and corrected minor bugs in the 'RunCollectionBubbleChartView' and the 'RunCollectionBoxPlotView' (ticket #1135).

File size: 23.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Drawing;
25using System.Linq;
26using System.Windows.Forms;
27using System.Windows.Forms.DataVisualization.Charting;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.MainForm;
32using HeuristicLab.MainForm.WindowsForms;
33
34namespace HeuristicLab.Optimization.Views {
35  [View("RunCollection BubbleChart")]
36  [Content(typeof(RunCollection), false)]
37  public partial class RunCollectionBubbleChartView : AsynchronousContentView {
38    private enum SizeDimension { Constant = 0 }
39    private enum AxisDimension { Index = 0 }
40
41    private string xAxisValue;
42    private string yAxisValue;
43    private string sizeAxisValue;
44
45    private Dictionary<int, Dictionary<object, double>> categoricalMapping;
46    private Dictionary<IRun, double> xJitter;
47    private Dictionary<IRun, double> yJitter;
48    private double xJitterFactor = 0.0;
49    private double yJitterFactor = 0.0;
50    private Random random;
51    private bool isSelecting = false;
52
53    public RunCollectionBubbleChartView() {
54      InitializeComponent();
55
56      categoricalMapping = new Dictionary<int, Dictionary<object, double>>();
57      xJitter = new Dictionary<IRun, double>();
58      yJitter = new Dictionary<IRun, double>();
59      random = new Random();
60      colorDialog.Color = Color.Black;
61      colorButton.Image = this.GenerateImage(16, 16, this.colorDialog.Color);
62      isSelecting = false;
63      chart.CustomizeAllChartAreas();
64      chart.ChartAreas[0].CursorX.Interval = 1;
65      chart.ChartAreas[0].CursorY.Interval = 1;
66      chart.ChartAreas[0].AxisX.ScaleView.Zoomable = !this.isSelecting;
67      chart.ChartAreas[0].AxisY.ScaleView.Zoomable = !this.isSelecting;
68    }
69
70    public new RunCollection Content {
71      get { return (RunCollection)base.Content; }
72      set { base.Content = value; }
73    }
74    public IStringConvertibleMatrix Matrix {
75      get { return this.Content; }
76    }
77
78    protected override void RegisterContentEvents() {
79      base.RegisterContentEvents();
80      Content.Reset += new EventHandler(Content_Reset);
81      Content.ColumnNamesChanged += new EventHandler(Content_ColumnNamesChanged);
82      Content.ItemsAdded += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsAdded);
83      Content.ItemsRemoved += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved);
84      Content.CollectionReset += new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset);
85      RegisterRunEvents(Content);
86    }
87    protected override void DeregisterContentEvents() {
88      base.DeregisterContentEvents();
89      Content.Reset -= new EventHandler(Content_Reset);
90      Content.ColumnNamesChanged -= new EventHandler(Content_ColumnNamesChanged);
91      Content.ItemsAdded -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsAdded);
92      Content.ItemsRemoved -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_ItemsRemoved);
93      Content.CollectionReset -= new HeuristicLab.Collections.CollectionItemsChangedEventHandler<IRun>(Content_CollectionReset);
94      DeregisterRunEvents(Content);
95    }
96    protected virtual void RegisterRunEvents(IEnumerable<IRun> runs) {
97      foreach (IRun run in runs)
98        run.Changed += new EventHandler(run_Changed);
99    }
100    protected virtual void DeregisterRunEvents(IEnumerable<IRun> runs) {
101      foreach (IRun run in runs)
102        run.Changed -= new EventHandler(run_Changed);
103    }
104
105    private void Content_CollectionReset(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IRun> e) {
106      DeregisterRunEvents(e.OldItems);
107      RegisterRunEvents(e.Items);
108    }
109    private void Content_ItemsRemoved(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IRun> e) {
110      DeregisterRunEvents(e.Items);
111    }
112    private void Content_ItemsAdded(object sender, HeuristicLab.Collections.CollectionItemsChangedEventArgs<IRun> e) {
113      RegisterRunEvents(e.Items);
114    }
115    private void run_Changed(object sender, EventArgs e) {
116      if (InvokeRequired)
117        this.Invoke(new EventHandler(run_Changed), sender, e);
118      else {
119        IRun run = (IRun)sender;
120        UpdateRun(run);
121      }
122    }
123
124    private void UpdateRun(IRun run) {
125      DataPoint point = this.chart.Series[0].Points.Where(p => p.Tag == run).SingleOrDefault();
126      if (point != null) {
127        point.Color = run.Color;
128        if (!run.Visible)
129          this.chart.Series[0].Points.Remove(point);
130      } else
131        AddDataPoint(run);
132      UpdateCursorInterval();
133      chart.ChartAreas[0].RecalculateAxesScale();
134
135
136      if (this.chart.Series[0].Points.Count == 0)
137        noRunsLabel.Visible = true;
138      else
139        noRunsLabel.Visible = false;
140    }
141
142    protected override void OnContentChanged() {
143      base.OnContentChanged();
144      this.categoricalMapping.Clear();
145      UpdateComboBoxes();
146      UpdateDataPoints();
147    }
148    private void Content_ColumnNamesChanged(object sender, EventArgs e) {
149      if (InvokeRequired)
150        Invoke(new EventHandler(Content_ColumnNamesChanged), sender, e);
151      else
152        UpdateComboBoxes();
153    }
154
155    private void UpdateComboBoxes() {
156      string selectedXAxis = (string)this.xAxisComboBox.SelectedItem;
157      string selectedYAxis = (string)this.yAxisComboBox.SelectedItem;
158      string selectedSizeAxis = (string)this.sizeComboBox.SelectedItem;
159      this.xAxisComboBox.Items.Clear();
160      this.yAxisComboBox.Items.Clear();
161      this.sizeComboBox.Items.Clear();
162      if (Content != null) {
163        string[] additionalAxisDimension = Enum.GetNames(typeof(AxisDimension));
164        this.xAxisComboBox.Items.AddRange(additionalAxisDimension);
165        this.xAxisComboBox.Items.AddRange(Matrix.ColumnNames.ToArray());
166        this.yAxisComboBox.Items.AddRange(additionalAxisDimension);
167        this.yAxisComboBox.Items.AddRange(Matrix.ColumnNames.ToArray());
168        string[] additionalSizeDimension = Enum.GetNames(typeof(SizeDimension));
169        this.sizeComboBox.Items.AddRange(additionalSizeDimension);
170        this.sizeComboBox.Items.AddRange(Matrix.ColumnNames.ToArray());
171        this.sizeComboBox.SelectedItem = SizeDimension.Constant.ToString();
172
173        bool changed = false;
174        if (selectedXAxis != null && xAxisComboBox.Items.Contains(selectedXAxis)) {
175          xAxisComboBox.SelectedItem = selectedXAxis;
176          changed = true;
177        }
178        if (selectedYAxis != null && yAxisComboBox.Items.Contains(selectedYAxis)) {
179          yAxisComboBox.SelectedItem = selectedYAxis;
180          changed = true;
181        }
182        if (selectedSizeAxis != null && sizeComboBox.Items.Contains(selectedSizeAxis)) {
183          sizeComboBox.SelectedItem = selectedSizeAxis;
184          changed = true;
185        }
186        if (changed)
187          UpdateDataPoints();
188      }
189    }
190
191    private void Content_Reset(object sender, EventArgs e) {
192      if (InvokeRequired)
193        Invoke(new EventHandler(Content_Reset), sender, e);
194      else {
195        this.categoricalMapping.Clear();
196        UpdateDataPoints();
197      }
198    }
199
200    private void UpdateDataPoints() {
201      Series series = this.chart.Series[0];
202      series.Points.Clear();
203      if (Content != null) {
204        foreach (IRun run in this.Content)
205          this.AddDataPoint(run);
206
207        //check to correct max bubble size
208        if (this.chart.Series[0].Points.Select(p => p.YValues[1]).Distinct().Count() == 1)
209          this.chart.Series[0]["BubbleMaxSize"] = "2";
210        else
211          this.chart.Series[0]["BubbleMaxSize"] = "7";
212
213        if (this.chart.Series[0].Points.Count == 0)
214          noRunsLabel.Visible = true;
215        else {
216          noRunsLabel.Visible = false;
217          UpdateCursorInterval();
218        }
219      }
220    }
221    private void AddDataPoint(IRun run) {
222      double? xValue;
223      double? yValue;
224      double? sizeValue;
225      Series series = this.chart.Series[0];
226      int row = this.Content.ToList().IndexOf(run);
227
228      if (!xAxisComboBox.DroppedDown)
229        this.xAxisValue = (string)xAxisComboBox.SelectedItem;
230      if (!yAxisComboBox.DroppedDown)
231        this.yAxisValue = (string)yAxisComboBox.SelectedItem;
232      if (!sizeComboBox.DroppedDown)
233        this.sizeAxisValue = (string)sizeComboBox.SelectedItem;
234
235      xValue = GetValue(run, this.xAxisValue);
236      yValue = GetValue(run, this.yAxisValue);
237      sizeValue = GetValue(run, this.sizeAxisValue);
238
239      if (xValue.HasValue && yValue.HasValue && sizeValue.HasValue) {
240        xValue = xValue.Value;
241        if (!xJitterFactor.IsAlmost(0.0))
242          xValue += 0.1 * GetXJitter(run) * xJitterFactor * (this.chart.ChartAreas[0].AxisX.Maximum - this.chart.ChartAreas[0].AxisX.Minimum);
243        yValue = yValue.Value;
244        if (!yJitterFactor.IsAlmost(0.0))
245          yValue += 0.1 * GetYJitter(run) * yJitterFactor * (this.chart.ChartAreas[0].AxisY.Maximum - this.chart.ChartAreas[0].AxisY.Minimum);
246        if (run.Visible) {
247          DataPoint point = new DataPoint(xValue.Value, new double[] { yValue.Value, sizeValue.Value });
248          point.Tag = run;
249          point.Color = run.Color;
250          series.Points.Add(point);
251        }
252      }
253    }
254    private double? GetValue(IRun run, string columnName) {
255      if (run == null || string.IsNullOrEmpty(columnName))
256        return null;
257
258      if (Enum.IsDefined(typeof(AxisDimension), columnName)) {
259        AxisDimension axisDimension = (AxisDimension)Enum.Parse(typeof(AxisDimension), columnName);
260        return GetValue(run, axisDimension);
261      } else if (Enum.IsDefined(typeof(SizeDimension), columnName)) {
262        SizeDimension sizeDimension = (SizeDimension)Enum.Parse(typeof(SizeDimension), columnName);
263        return GetValue(run, sizeDimension);
264      } else {
265        int columnIndex = Matrix.ColumnNames.ToList().IndexOf(columnName);
266        IItem value = Content.GetValue(run, columnIndex);
267        if (value == null)
268          return null;
269
270        DoubleValue doubleValue = value as DoubleValue;
271        IntValue intValue = value as IntValue;
272        TimeSpanValue timeSpanValue = value as TimeSpanValue;
273        double? ret = null;
274        if (doubleValue != null) {
275          if (!double.IsNaN(doubleValue.Value) && !double.IsInfinity(doubleValue.Value))
276            ret = doubleValue.Value;
277        } else if (intValue != null)
278          ret = intValue.Value;
279        else if (timeSpanValue != null) {
280          ret = timeSpanValue.Value.TotalSeconds;
281        } else
282          ret = GetCategoricalValue(columnIndex, value.ToString());
283
284        return ret;
285      }
286    }
287    private double GetCategoricalValue(int dimension, string value) {
288      if (!this.categoricalMapping.ContainsKey(dimension))
289        this.categoricalMapping[dimension] = new Dictionary<object, double>();
290      if (!this.categoricalMapping[dimension].ContainsKey(value)) {
291        if (this.categoricalMapping[dimension].Values.Count == 0)
292          this.categoricalMapping[dimension][value] = 1.0;
293        else
294          this.categoricalMapping[dimension][value] = this.categoricalMapping[dimension].Values.Max() + 1.0;
295      }
296      return this.categoricalMapping[dimension][value];
297    }
298    private double GetValue(IRun run, AxisDimension axisDimension) {
299      double value = double.NaN;
300      switch (axisDimension) {
301        case AxisDimension.Index: {
302            value = Content.ToList().IndexOf(run);
303            break;
304          }
305        default: {
306            throw new ArgumentException("No handling strategy for " + axisDimension.ToString() + " is defined.");
307          }
308      }
309      return value;
310    }
311    private double GetValue(IRun run, SizeDimension sizeDimension) {
312      double value = double.NaN;
313      switch (sizeDimension) {
314        case SizeDimension.Constant: {
315            value = 2;
316            break;
317          }
318        default: {
319            throw new ArgumentException("No handling strategy for " + sizeDimension.ToString() + " is defined.");
320          }
321      }
322      return value;
323    }
324    private void UpdateCursorInterval() {
325      Series series = chart.Series[0];
326      double[] xValues = (from point in series.Points
327                          where !point.IsEmpty
328                          select point.XValue)
329                    .DefaultIfEmpty(1.0)
330                    .ToArray();
331      double[] yValues = (from point in series.Points
332                          where !point.IsEmpty
333                          select point.YValues[0])
334                    .DefaultIfEmpty(1.0)
335                    .ToArray();
336
337      double xRange = xValues.Max() - xValues.Min();
338      double yRange = yValues.Max() - yValues.Min();
339      if (xRange.IsAlmost(0.0)) xRange = 1.0;
340      if (yRange.IsAlmost(0.0)) yRange = 1.0;
341      double xDigits = (int)Math.Log10(xRange) - 3;
342      double yDigits = (int)Math.Log10(yRange) - 3;
343      double xZoomInterval = Math.Pow(10, xDigits);
344      double yZoomInterval = Math.Pow(10, yDigits);
345      this.chart.ChartAreas[0].CursorX.Interval = xZoomInterval;
346      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
347
348      //code to handle TimeSpanValues correct
349      int axisDimensionCount = Enum.GetNames(typeof(AxisDimension)).Count();
350      int columnIndex = xAxisComboBox.SelectedIndex - axisDimensionCount;
351      if (columnIndex >= 0 && Content.GetValue(0, columnIndex) is TimeSpanValue)
352        this.chart.ChartAreas[0].CursorX.Interval = 1;
353      columnIndex = yAxisComboBox.SelectedIndex - axisDimensionCount;
354      if (columnIndex >= 0 && Content.GetValue(0, columnIndex) is TimeSpanValue)
355        this.chart.ChartAreas[0].CursorY.Interval = 1;
356    }
357
358    #region drag and drop and tooltip
359    private IRun draggedRun;
360    private void chart_MouseDown(object sender, MouseEventArgs e) {
361      HitTestResult h = this.chart.HitTest(e.X, e.Y);
362      if (h.ChartElementType == ChartElementType.DataPoint) {
363        IRun run = (IRun)((DataPoint)h.Object).Tag;
364        if (e.Clicks >= 2) {
365          IContentView view = MainFormManager.MainForm.ShowContent(run);
366          if (view != null) {
367            view.ReadOnly = this.ReadOnly;
368            view.Locked = this.Locked;
369          }
370        } else
371          this.draggedRun = run;
372        this.chart.ChartAreas[0].CursorX.SetSelectionPosition(double.NaN, double.NaN);
373        this.chart.ChartAreas[0].CursorY.SetSelectionPosition(double.NaN, double.NaN);
374      }
375    }
376
377    private void chart_MouseUp(object sender, MouseEventArgs e) {
378      if (isSelecting) {
379        System.Windows.Forms.DataVisualization.Charting.Cursor xCursor = chart.ChartAreas[0].CursorX;
380        System.Windows.Forms.DataVisualization.Charting.Cursor yCursor = chart.ChartAreas[0].CursorY;
381
382        double minX = Math.Min(xCursor.SelectionStart, xCursor.SelectionEnd);
383        double maxX = Math.Max(xCursor.SelectionStart, xCursor.SelectionEnd);
384        double minY = Math.Min(yCursor.SelectionStart, yCursor.SelectionEnd);
385        double maxY = Math.Max(yCursor.SelectionStart, yCursor.SelectionEnd);
386
387        //check for click to select model
388        if (minX == maxX && minY == maxY) {
389          HitTestResult hitTest = chart.HitTest(e.X, e.Y);
390          if (hitTest.ChartElementType == ChartElementType.DataPoint) {
391            int pointIndex = hitTest.PointIndex;
392            IRun run = (IRun)this.chart.Series[0].Points[pointIndex].Tag;
393            run.Color = colorDialog.Color;
394          }
395        } else {
396          List<DataPoint> selectedPoints = new List<DataPoint>();
397          foreach (DataPoint p in this.chart.Series[0].Points) {
398            if (p.XValue >= minX && p.XValue < maxX &&
399              p.YValues[0] >= minY && p.YValues[0] < maxY) {
400              selectedPoints.Add(p);
401            }
402          }
403          foreach (DataPoint p in selectedPoints) {
404            IRun run = (IRun)p.Tag;
405            run.Color = colorDialog.Color;
406          }
407        }
408        this.chart.ChartAreas[0].CursorX.SelectionStart = this.chart.ChartAreas[0].CursorX.SelectionEnd;
409        this.chart.ChartAreas[0].CursorY.SelectionStart = this.chart.ChartAreas[0].CursorY.SelectionEnd;
410      }
411    }
412
413    private void chart_MouseMove(object sender, MouseEventArgs e) {
414      HitTestResult h = this.chart.HitTest(e.X, e.Y);
415      if (!Locked) {
416        if (this.draggedRun != null && h.ChartElementType != ChartElementType.DataPoint) {
417          DataObject data = new DataObject();
418          data.SetData("Type", draggedRun.GetType());
419          data.SetData("Value", draggedRun);
420          if (ReadOnly)
421            DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
422          else {
423            DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
424            if ((result & DragDropEffects.Move) == DragDropEffects.Move)
425              Content.Remove(draggedRun);
426          }
427          this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = !isSelecting;
428          this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = !isSelecting;
429          this.draggedRun = null;
430        }
431      }
432
433      string newTooltipText = string.Empty;
434      string oldTooltipText;
435      if (h.ChartElementType == ChartElementType.DataPoint) {
436        IRun run = (IRun)((DataPoint)h.Object).Tag;
437        newTooltipText = BuildTooltip(run);
438      } else if (h.ChartElementType == ChartElementType.AxisLabels) {
439        newTooltipText = ((CustomLabel)h.Object).ToolTip;
440      }
441
442      oldTooltipText = this.tooltip.GetToolTip(chart);
443      if (newTooltipText != oldTooltipText)
444        this.tooltip.SetToolTip(chart, newTooltipText);
445    }
446
447    private string BuildTooltip(IRun run) {
448      string tooltip;
449      tooltip = run.Name + System.Environment.NewLine;
450
451      double? xValue = this.GetValue(run, (string)xAxisComboBox.SelectedItem);
452      double? yValue = this.GetValue(run, (string)yAxisComboBox.SelectedItem);
453      double? sizeValue = this.GetValue(run, (string)sizeComboBox.SelectedItem);
454
455      string xString = xValue == null ? string.Empty : xValue.Value.ToString();
456      string yString = yValue == null ? string.Empty : yValue.Value.ToString();
457      string sizeString = sizeValue == null ? string.Empty : sizeValue.Value.ToString();
458
459      //code to handle TimeSpanValues correct
460      int axisDimensionCount = Enum.GetNames(typeof(AxisDimension)).Count();
461      int columnIndex = xAxisComboBox.SelectedIndex - axisDimensionCount;
462      if (xValue.HasValue && columnIndex > 0 && Content.GetValue(0, columnIndex) is TimeSpanValue) {
463        TimeSpan time = TimeSpan.FromSeconds(xValue.Value);
464        xString = string.Format("{0:00}:{1:00}:{2:00.00}", (int)time.TotalHours, time.Minutes, time.Seconds);
465      }
466      columnIndex = yAxisComboBox.SelectedIndex - axisDimensionCount;
467      if (yValue.HasValue && columnIndex > 0 && Content.GetValue(0, columnIndex) is TimeSpanValue) {
468        TimeSpan time = TimeSpan.FromSeconds(yValue.Value);
469        yString = string.Format("{0:00}:{1:00}:{2:00.00}", (int)time.TotalHours, time.Minutes, time.Seconds);
470      }
471
472      tooltip += xAxisComboBox.SelectedItem + " : " + xString + Environment.NewLine;
473      tooltip += yAxisComboBox.SelectedItem + " : " + yString + Environment.NewLine;
474      tooltip += sizeComboBox.SelectedItem + " : " + sizeString + Environment.NewLine;
475
476      return tooltip;
477    }
478    #endregion
479
480    #region GUI events and updating
481    private double GetXJitter(IRun run) {
482      if (!this.xJitter.ContainsKey(run))
483        this.xJitter[run] = random.NextDouble() * 2.0 - 1.0;
484      return this.xJitter[run];
485    }
486    private double GetYJitter(IRun run) {
487      if (!this.yJitter.ContainsKey(run))
488        this.yJitter[run] = random.NextDouble() * 2.0 - 1.0;
489      return this.yJitter[run];
490    }
491    private void jitterTrackBar_ValueChanged(object sender, EventArgs e) {
492      this.xJitterFactor = xTrackBar.Value / 100.0;
493      this.yJitterFactor = yTrackBar.Value / 100.0;
494      this.UpdateDataPoints();
495    }
496
497    private void AxisComboBox_SelectedIndexChanged(object sender, EventArgs e) {
498      UpdateDataPoints();
499      UpdateAxisLabels();
500    }
501    private void UpdateAxisLabels() {
502      Axis xAxis = this.chart.ChartAreas[0].AxisX;
503      Axis yAxis = this.chart.ChartAreas[0].AxisY;
504      int axisDimensionCount = Enum.GetNames(typeof(AxisDimension)).Count();
505      SetCustomAxisLabels(xAxis, xAxisComboBox.SelectedIndex - axisDimensionCount);
506      SetCustomAxisLabels(yAxis, yAxisComboBox.SelectedIndex - axisDimensionCount);
507      if (xAxisComboBox.SelectedItem != null)
508        xAxis.Title = xAxisComboBox.SelectedItem.ToString();
509      if (yAxisComboBox.SelectedItem != null)
510        yAxis.Title = yAxisComboBox.SelectedItem.ToString();
511    }
512
513    private void chart_AxisViewChanged(object sender, System.Windows.Forms.DataVisualization.Charting.ViewEventArgs e) {
514      this.UpdateAxisLabels();
515    }
516
517    private void SetCustomAxisLabels(Axis axis, int dimension) {
518      axis.CustomLabels.Clear();
519      if (categoricalMapping.ContainsKey(dimension)) {
520        foreach (var pair in categoricalMapping[dimension]) {
521          string labelText = pair.Key.ToString();
522          CustomLabel label = new CustomLabel();
523          label.ToolTip = labelText;
524          if (labelText.Length > 25)
525            labelText = labelText.Substring(0, 25) + " ... ";
526          label.Text = labelText;
527          label.GridTicks = GridTickTypes.TickMark;
528          label.FromPosition = pair.Value - 0.5;
529          label.ToPosition = pair.Value + 0.5;
530          axis.CustomLabels.Add(label);
531        }
532      } else if (dimension > 0 && Content.GetValue(0, dimension) is TimeSpanValue) {
533        this.chart.ChartAreas[0].RecalculateAxesScale();
534        for (double i = axis.Minimum; i <= axis.Maximum; i += axis.LabelStyle.Interval) {
535          TimeSpan time = TimeSpan.FromSeconds(i);
536          string x = string.Format("{0:00}:{1:00}:{2:00}", (int)time.Hours, time.Minutes, time.Seconds);
537          axis.CustomLabels.Add(i - axis.LabelStyle.Interval / 2, i + axis.LabelStyle.Interval / 2, x);
538        }
539      }
540    }
541
542    private void zoomButton_CheckedChanged(object sender, EventArgs e) {
543      this.isSelecting = selectButton.Checked;
544      this.colorButton.Enabled = this.isSelecting;
545      this.chart.ChartAreas[0].AxisX.ScaleView.Zoomable = !isSelecting;
546      this.chart.ChartAreas[0].AxisY.ScaleView.Zoomable = !isSelecting;
547    }
548    private void colorButton_Click(object sender, EventArgs e) {
549      if (colorDialog.ShowDialog(this) == DialogResult.OK) {
550        this.colorButton.Image = this.GenerateImage(16, 16, this.colorDialog.Color);
551      }
552    }
553    private Image GenerateImage(int width, int height, Color fillColor) {
554      Image colorImage = new Bitmap(width, height);
555      using (Graphics gfx = Graphics.FromImage(colorImage)) {
556        using (SolidBrush brush = new SolidBrush(fillColor)) {
557          gfx.FillRectangle(brush, 0, 0, width, height);
558        }
559      }
560      return colorImage;
561    }
562    #endregion
563  }
564}
Note: See TracBrowser for help on using the repository browser.