Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
04/16/13 13:13:41 (11 years ago)
Author:
spimming
Message:

#1888:

  • Merged revisions from trunk
Location:
branches/OaaS
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/OaaS

  • branches/OaaS/HeuristicLab.Analysis.Views

    • Property svn:mergeinfo set to (toggle deleted branches)
      /trunk/sources/HeuristicLab.Analysis.Viewsmergedeligible
      /branches/Algorithms.GradientDescent/HeuristicLab.Analysis.Views5516-5520
      /branches/Benchmarking/sources/HeuristicLab.Analysis.Views6917-7005
      /branches/CMAES/HeuristicLab.Analysis.Views9141-9257
      /branches/CloningRefactoring/HeuristicLab.Analysis.Views4656-4721
      /branches/DataAnalysis Refactoring/HeuristicLab.Analysis.Views5471-5808
      /branches/DataAnalysis SolutionEnsembles/HeuristicLab.Analysis.Views5815-6180
      /branches/DataAnalysis/HeuristicLab.Analysis.Views4458-4459,​4462,​4464
      /branches/GP.Grammar.Editor/HeuristicLab.Analysis.Views6284-6795
      /branches/GP.Symbols (TimeLag, Diff, Integral)/HeuristicLab.Analysis.Views5060
      /branches/NET40/sources/HeuristicLab.Analysis.Views5138-5162
      /branches/ParallelEngine/HeuristicLab.Analysis.Views5175-5192
      /branches/ProblemInstancesRegressionAndClassification/HeuristicLab.Analysis.Views7568-7810
      /branches/QAPAlgorithms/HeuristicLab.Analysis.Views6350-6627
      /branches/Restructure trunk solution/HeuristicLab.Analysis.Views6828
      /branches/RuntimeOptimizer/HeuristicLab.Analysis.Views8943-9078
      /branches/ScatterSearch (trunk integration)/HeuristicLab.Analysis.Views7787-8333
      /branches/SlaveShutdown/HeuristicLab.Analysis.Views8944-8956
      /branches/SuccessProgressAnalysis/HeuristicLab.Analysis.Views5370-5682
      /branches/Trunk/HeuristicLab.Analysis.Views6829-6865
      /branches/UnloadJobs/HeuristicLab.Analysis.Views9168-9215
      /branches/VNS/HeuristicLab.Analysis.Views5594-5752
      /branches/histogram/HeuristicLab.Analysis.Views5959-6341
  • branches/OaaS/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs

    r7829 r9363  
    1 #region License Information
     1#region License Information
    22/* HeuristicLab
    33 * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     
    2121
    2222using System;
     23using System.Collections.Generic;
    2324using System.Drawing;
     25using System.Linq;
    2426using System.Windows.Forms;
     27using System.Windows.Forms.DataVisualization.Charting;
    2528using HeuristicLab.Collections;
     29using HeuristicLab.Common;
    2630using HeuristicLab.Core.Views;
    2731using HeuristicLab.MainForm;
     
    3034  [View("ScatterPlot View")]
    3135  [Content(typeof(ScatterPlot), true)]
    32   public partial class ScatterPlotView : NamedItemView {
     36  public partial class ScatterPlotView : NamedItemView, IConfigureableView {
     37    protected List<Series> invisibleSeries;
     38    protected Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow> pointsRowsTable;
     39
    3340    public new ScatterPlot Content {
    3441      get { return (ScatterPlot)base.Content; }
     
    3845    public ScatterPlotView() {
    3946      InitializeComponent();
     47      pointsRowsTable = new Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow>();
     48      invisibleSeries = new List<Series>();
    4049      chart.CustomizeAllChartAreas();
    41     }
    42 
     50      chart.ChartAreas[0].CursorX.Interval = 1;
     51    }
     52
     53    #region Event Handler Registration
    4354    protected override void DeregisterContentEvents() {
    44       Content.Points.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
    45       Content.Points.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
    46       Content.Points.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
    47       Content.Points.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
    48       Content.AxisNameChanged -= new EventHandler(Content_AxisNameChanged);
     55      foreach (ScatterPlotDataRow row in Content.Rows)
     56        DeregisterScatterPlotDataRowEvents(row);
     57      Content.VisualPropertiesChanged -= new EventHandler(Content_VisualPropertiesChanged);
     58      Content.Rows.ItemsAdded -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);
     59      Content.Rows.ItemsRemoved -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved);
     60      Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);
     61      Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);
    4962      base.DeregisterContentEvents();
    5063    }
    51 
    5264    protected override void RegisterContentEvents() {
    5365      base.RegisterContentEvents();
    54       Content.Points.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
    55       Content.Points.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
    56       Content.Points.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
    57       Content.Points.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
    58       Content.AxisNameChanged += new EventHandler(Content_AxisNameChanged);
    59     }
    60 
    61     private void Content_Points_Changed(object sender, CollectionItemsChangedEventArgs<IndexedItem<PointF>> e) {
    62       RedrawChart();
    63     }
     66      Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);
     67      Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);
     68      Content.Rows.ItemsRemoved += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved);
     69      Content.Rows.ItemsReplaced += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);
     70      Content.Rows.CollectionReset += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);
     71    }
     72
     73    protected virtual void RegisterScatterPlotDataRowEvents(ScatterPlotDataRow row) {
     74      row.NameChanged += new EventHandler(Row_NameChanged);
     75      row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
     76      pointsRowsTable.Add(row.Points, row);
     77      row.Points.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);
     78      row.Points.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);
     79      row.Points.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);
     80      row.Points.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);
     81    }
     82    protected virtual void DeregisterScatterPlotDataRowEvents(ScatterPlotDataRow row) {
     83      row.Points.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);
     84      row.Points.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);
     85      row.Points.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);
     86      row.Points.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);
     87      pointsRowsTable.Remove(row.Points);
     88      row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);
     89      row.NameChanged -= new EventHandler(Row_NameChanged);
     90    }
     91    #endregion
    6492
    6593    protected override void OnContentChanged() {
    6694      base.OnContentChanged();
     95      invisibleSeries.Clear();
     96      chart.Titles[0].Text = string.Empty;
     97      chart.ChartAreas[0].AxisX.Title = string.Empty;
     98      chart.ChartAreas[0].AxisY.Title = string.Empty;
     99      chart.Series.Clear();
    67100      if (Content != null) {
    68         ConfigureChart();
    69         RedrawChart();
     101        chart.Titles[0].Text = Content.Name;
     102        AddScatterPlotDataRows(Content.Rows);
     103        ConfigureChartArea(chart.ChartAreas[0]);
     104        RecalculateAxesScale(chart.ChartAreas[0]);
     105      }
     106    }
     107
     108    protected override void SetEnabledStateOfControls() {
     109      base.SetEnabledStateOfControls();
     110      chart.Enabled = Content != null;
     111    }
     112
     113    public void ShowConfiguration() {
     114      if (Content != null) {
     115        using (ScatterPlotVisualPropertiesDialog dialog = new ScatterPlotVisualPropertiesDialog(Content)) {
     116          dialog.ShowDialog(this);
     117        }
     118      } else MessageBox.Show("Nothing to configure.");
     119    }
     120
     121    protected virtual void AddScatterPlotDataRows(IEnumerable<ScatterPlotDataRow> rows) {
     122      foreach (var row in rows) {
     123        RegisterScatterPlotDataRowEvents(row);
     124        Series series = new Series(row.Name);
     125        if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
     126        else series.LegendText = row.Name;
     127        ConfigureSeries(series, row);
     128        FillSeriesWithRowValues(series, row);
     129        chart.Series.Add(series);
     130      }
     131      ConfigureChartArea(chart.ChartAreas[0]);
     132      RecalculateAxesScale(chart.ChartAreas[0]);
     133      UpdateYCursorInterval();
     134    }
     135
     136    protected virtual void RemoveScatterPlotDataRows(IEnumerable<ScatterPlotDataRow> rows) {
     137      foreach (var row in rows) {
     138        DeregisterScatterPlotDataRowEvents(row);
     139        Series series = chart.Series[row.Name];
     140        chart.Series.Remove(series);
     141        if (invisibleSeries.Contains(series))
     142          invisibleSeries.Remove(series);
     143      }
     144      RecalculateAxesScale(chart.ChartAreas[0]);
     145    }
     146
     147    private void ConfigureSeries(Series series, ScatterPlotDataRow row) {
     148      series.BorderWidth = 1;
     149      series.BorderDashStyle = ChartDashStyle.Solid;
     150      series.BorderColor = Color.Empty;
     151
     152      if (row.VisualProperties.Color != Color.Empty)
     153        series.Color = row.VisualProperties.Color;
     154      else series.Color = Color.Empty;
     155      series.IsVisibleInLegend = row.VisualProperties.IsVisibleInLegend;
     156      series.ChartType = SeriesChartType.FastPoint;
     157      series.MarkerSize = row.VisualProperties.PointSize;
     158      series.MarkerStyle = ConvertPointStyle(row.VisualProperties.PointStyle);
     159      series.XAxisType = AxisType.Primary;
     160      series.YAxisType = AxisType.Primary;
     161
     162      if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
     163      else series.LegendText = row.Name;
     164
     165      string xAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.XAxisTitle)
     166                      ? "X"
     167                      : Content.VisualProperties.XAxisTitle;
     168      string yAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.YAxisTitle)
     169                            ? "Y"
     170                            : Content.VisualProperties.YAxisTitle;
     171      series.ToolTip =
     172        series.LegendText + Environment.NewLine +
     173        xAxisTitle + " = " + "#VALX," + Environment.NewLine +
     174        yAxisTitle + " = " + "#VAL";
     175    }
     176
     177    private void ConfigureChartArea(ChartArea area) {
     178      if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;
     179      if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;
     180      chart.Titles[0].Text = Content.VisualProperties.Title;
     181
     182      if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;
     183      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor;
     184      area.AxisX.Title = Content.VisualProperties.XAxisTitle;
     185      area.AxisX.MajorGrid.Enabled = Content.VisualProperties.XAxisGrid;
     186
     187      if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont;
     188      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor;
     189      area.AxisY.Title = Content.VisualProperties.YAxisTitle;
     190      area.AxisY.MajorGrid.Enabled = Content.VisualProperties.YAxisGrid;
     191    }
     192
     193    private void RecalculateAxesScale(ChartArea area) {
     194      // Reset the axes bounds so that RecalculateAxesScale() will assign new bounds
     195      foreach (Axis a in area.Axes) {
     196        a.Minimum = double.NaN;
     197        a.Maximum = double.NaN;
     198      }
     199      area.RecalculateAxesScale();
     200      area.AxisX.IsMarginVisible = false;
     201
     202      if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue;
     203      if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue;
     204      if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue;
     205      if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue;
     206      if (area.AxisX.Minimum >= area.AxisX.Maximum) area.AxisX.Maximum = area.AxisX.Minimum + 1;
     207      if (area.AxisY.Minimum >= area.AxisY.Maximum) area.AxisY.Maximum = area.AxisY.Minimum + 1;
     208    }
     209
     210    protected virtual void UpdateYCursorInterval() {
     211      double interestingValuesRange = (
     212        from series in chart.Series
     213        where series.Enabled
     214        let values = (from point in series.Points
     215                      where !point.IsEmpty
     216                      select point.YValues[0]).DefaultIfEmpty(1.0)
     217        let range = values.Max() - values.Min()
     218        where range > 0.0
     219        select range
     220        ).DefaultIfEmpty(1.0).Min();
     221
     222      double digits = (int)Math.Log10(interestingValuesRange) - 3;
     223      double yZoomInterval = Math.Pow(10, digits);
     224      this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
     225    }
     226
     227    #region Event Handlers
     228    #region Content Event Handlers
     229    protected override void Content_NameChanged(object sender, EventArgs e) {
     230      if (InvokeRequired)
     231        Invoke(new EventHandler(Content_NameChanged), sender, e);
     232      else {
     233        chart.Titles[0].Text = Content.Name;
     234        base.Content_NameChanged(sender, e);
     235      }
     236    }
     237    private void Content_VisualPropertiesChanged(object sender, EventArgs e) {
     238      if (InvokeRequired)
     239        Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e);
     240      else {
     241        ConfigureChartArea(chart.ChartAreas[0]);
     242        RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed
     243      }
     244    }
     245    #endregion
     246    #region Rows Event Handlers
     247    private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
     248      if (InvokeRequired)
     249        Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded), sender, e);
     250      else {
     251        AddScatterPlotDataRows(e.Items);
     252      }
     253    }
     254    private void Rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
     255      if (InvokeRequired)
     256        Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved), sender, e);
     257      else {
     258        RemoveScatterPlotDataRows(e.Items);
     259      }
     260    }
     261    private void Rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
     262      if (InvokeRequired)
     263        Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced), sender, e);
     264      else {
     265        RemoveScatterPlotDataRows(e.OldItems);
     266        AddScatterPlotDataRows(e.Items);
     267      }
     268    }
     269    private void Rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
     270      if (InvokeRequired)
     271        Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset), sender, e);
     272      else {
     273        RemoveScatterPlotDataRows(e.OldItems);
     274        AddScatterPlotDataRows(e.Items);
     275      }
     276    }
     277    #endregion
     278    #region Row Event Handlers
     279    private void Row_VisualPropertiesChanged(object sender, EventArgs e) {
     280      if (InvokeRequired)
     281        Invoke(new EventHandler(Row_VisualPropertiesChanged), sender, e);
     282      else {
     283        ScatterPlotDataRow row = (ScatterPlotDataRow)sender;
     284        Series series = chart.Series[row.Name];
     285        series.Points.Clear();
     286        ConfigureSeries(series, row);
     287        FillSeriesWithRowValues(series, row);
     288        RecalculateAxesScale(chart.ChartAreas[0]);
     289      }
     290    }
     291    private void Row_NameChanged(object sender, EventArgs e) {
     292      if (InvokeRequired)
     293        Invoke(new EventHandler(Row_NameChanged), sender, e);
     294      else {
     295        ScatterPlotDataRow row = (ScatterPlotDataRow)sender;
     296        chart.Series[row.Name].Name = row.Name;
     297      }
     298    }
     299    #endregion
     300    #region Points Event Handlers
     301    private void Points_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
     302      if (InvokeRequired)
     303        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded), sender, e);
     304      else {
     305        ScatterPlotDataRow row = null;
     306        pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
     307        if (row != null) {
     308          Series rowSeries = chart.Series[row.Name];
     309          if (!invisibleSeries.Contains(rowSeries)) {
     310            rowSeries.Points.Clear();
     311            FillSeriesWithRowValues(rowSeries, row);
     312            RecalculateAxesScale(chart.ChartAreas[0]);
     313            UpdateYCursorInterval();
     314          }
     315        }
     316      }
     317    }
     318    private void Points_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
     319      if (InvokeRequired)
     320        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved), sender, e);
     321      else {
     322        ScatterPlotDataRow row = null;
     323        pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
     324        if (row != null) {
     325          Series rowSeries = chart.Series[row.Name];
     326          if (!invisibleSeries.Contains(rowSeries)) {
     327            rowSeries.Points.Clear();
     328            FillSeriesWithRowValues(rowSeries, row);
     329            RecalculateAxesScale(chart.ChartAreas[0]);
     330            UpdateYCursorInterval();
     331          }
     332        }
     333      }
     334    }
     335    private void Points_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
     336      if (InvokeRequired)
     337        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced), sender, e);
     338      else {
     339        ScatterPlotDataRow row = null;
     340        pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
     341        if (row != null) {
     342          Series rowSeries = chart.Series[row.Name];
     343          if (!invisibleSeries.Contains(rowSeries)) {
     344            rowSeries.Points.Clear();
     345            FillSeriesWithRowValues(rowSeries, row);
     346            RecalculateAxesScale(chart.ChartAreas[0]);
     347            UpdateYCursorInterval();
     348          }
     349        }
     350      }
     351    }
     352    private void Points_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
     353      if (InvokeRequired)
     354        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset), sender, e);
     355      else {
     356        ScatterPlotDataRow row = null;
     357        pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
     358        if (row != null) {
     359          Series rowSeries = chart.Series[row.Name];
     360          if (!invisibleSeries.Contains(rowSeries)) {
     361            rowSeries.Points.Clear();
     362            FillSeriesWithRowValues(rowSeries, row);
     363            RecalculateAxesScale(chart.ChartAreas[0]);
     364            UpdateYCursorInterval();
     365          }
     366        }
     367      }
     368    }
     369    #endregion
     370    #endregion
     371
     372    #region Chart Event Handlers
     373    private void chart_MouseDown(object sender, MouseEventArgs e) {
     374      HitTestResult result = chart.HitTest(e.X, e.Y);
     375      if (result.ChartElementType == ChartElementType.LegendItem) {
     376        ToggleSeriesVisible(result.Series);
     377      }
     378    }
     379    private void chart_MouseMove(object sender, MouseEventArgs e) {
     380      HitTestResult result = chart.HitTest(e.X, e.Y);
     381      if (result.ChartElementType == ChartElementType.LegendItem)
     382        this.Cursor = Cursors.Hand;
     383      else
     384        this.Cursor = Cursors.Default;
     385    }
     386    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
     387      foreach (LegendItem legendItem in e.LegendItems) {
     388        var series = chart.Series[legendItem.SeriesName];
     389        if (series != null) {
     390          bool seriesIsInvisible = invisibleSeries.Contains(series);
     391          foreach (LegendCell cell in legendItem.Cells) {
     392            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
     393          }
     394        }
     395      }
     396    }
     397    #endregion
     398
     399    private void ToggleSeriesVisible(Series series) {
     400      if (!invisibleSeries.Contains(series)) {
     401        series.Points.Clear();
     402        invisibleSeries.Add(series);
    70403      } else {
    71         ClearChart();
    72       }
    73     }
    74 
    75     private void Content_AxisNameChanged(object sender, EventArgs e) {
    76       ConfigureChart();
    77     }
    78 
    79     private void ConfigureChart() {
    80       if (InvokeRequired) {
    81         Invoke((Action)ConfigureChart);
    82       } else {
    83         chart.ChartAreas[0].AxisX.Title = Content.XAxisName;
    84         chart.ChartAreas[0].AxisY.Title = Content.YAxisName;
    85         chart.Titles[0].Text = Content.Name;
    86       }
    87     }
    88 
    89     private void ClearChart() {
    90       if (InvokeRequired) {
    91         Invoke((Action)ClearChart);
    92       } else {
    93         chart.Series[0].Points.Clear();
    94         chart.ChartAreas[0].AxisX.Title = String.Empty;
    95         chart.ChartAreas[0].AxisY.Title = String.Empty;
    96         chart.Titles[0].Text = String.Empty;
    97       }
    98     }
    99 
    100     private void RedrawChart() {
    101       if (InvokeRequired) {
    102         Invoke((Action)RedrawChart);
    103       } else {
    104         chart.Series[0].Points.SuspendUpdates();
    105         chart.Series[0].Points.Clear();
    106         foreach (var p in Content.Points.ToArray()) {
    107           chart.Series[0].Points.AddXY(p.X, p.Y);
    108         }
    109         chart.Series[0].Points.ResumeUpdates();
    110       }
    111     }
     404        invisibleSeries.Remove(series);
     405        if (Content != null) {
     406
     407          var row = (from r in Content.Rows
     408                     where r.Name == series.Name
     409                     select r).Single();
     410          FillSeriesWithRowValues(series, row);
     411          this.chart.Legends[series.Legend].ForeColor = Color.Black;
     412          RecalculateAxesScale(chart.ChartAreas[0]);
     413          UpdateYCursorInterval();
     414        }
     415      }
     416    }
     417
     418    private void FillSeriesWithRowValues(Series series, ScatterPlotDataRow row) {
     419      for (int i = 0; i < row.Points.Count; i++) {
     420        var value = row.Points[i];
     421        DataPoint point = new DataPoint();
     422        if (IsInvalidValue(value.X) || IsInvalidValue(value.Y))
     423          point.IsEmpty = true;
     424        else {
     425          point.XValue = value.X;
     426          point.YValues = new double[] { value.Y };
     427        }
     428        series.Points.Add(point);
     429      }
     430    }
     431
     432    #region Helpers
     433    public static IEnumerable<double> DoubleRange(double min, double max, double step) {
     434      double i;
     435      for (i = min; i <= max; i += step)
     436        yield return i;
     437
     438      if (i != max + step)
     439        yield return i;
     440    }
     441
     442    private double HumanRoundRange(double range) {
     443      double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range)));
     444      double rounding = range / base10;
     445      if (rounding <= 1.5) rounding = 1;
     446      else if (rounding <= 2.25) rounding = 2;
     447      else if (rounding <= 3.75) rounding = 2.5;
     448      else if (rounding <= 7.5) rounding = 5;
     449      else rounding = 10;
     450      return rounding * base10;
     451    }
     452
     453    private double HumanRoundMax(double max) {
     454      double base10;
     455      if (max > 0) base10 = Math.Pow(10.0, Math.Floor(Math.Log10(max)));
     456      else base10 = Math.Pow(10.0, Math.Ceiling(Math.Log10(-max)));
     457      double rounding = (max > 0) ? base10 : -base10;
     458      while (rounding < max) rounding += base10;
     459      return rounding;
     460    }
     461
     462    private MarkerStyle ConvertPointStyle(ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle pointStyle) {
     463      switch (pointStyle) {
     464        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Circle:
     465          return MarkerStyle.Circle;
     466        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Cross:
     467          return MarkerStyle.Cross;
     468        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Diamond:
     469          return MarkerStyle.Diamond;
     470        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Square:
     471          return MarkerStyle.Square;
     472        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star4:
     473          return MarkerStyle.Star4;
     474        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star5:
     475          return MarkerStyle.Star5;
     476        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star6:
     477          return MarkerStyle.Star6;
     478        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star10:
     479          return MarkerStyle.Star10;
     480        case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Triangle:
     481          return MarkerStyle.Triangle;
     482        default:
     483          return MarkerStyle.None;
     484      }
     485    }
     486
     487    protected static bool IsInvalidValue(double x) {
     488      return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;
     489    }
     490    #endregion
    112491  }
    113492}
Note: See TracChangeset for help on using the changeset viewer.