Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 4812 was 4812, checked in by mkommend, 12 years ago

Deactivated jitter and automatic coloring if no axis are chosen in the RunCollectionBubbleChartView (ticket #1272).

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