Changeset 14439


Ignore:
Timestamp:
12/02/16 13:06:49 (2 years ago)
Author:
pfleck
Message:

#2713 Moved the charting logic out of DataTableView and ScatterPlotView into new DataTableControl and ScatterPlotControl.
This way, the charts can be reused without the name-textbox and description from the NamedItemView.

Location:
trunk/sources/HeuristicLab.Analysis.Views/3.3
Files:
5 edited
4 copied

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableControl.Designer.cs

    r14435 r14439  
    2121
    2222namespace HeuristicLab.Analysis.Views {
    23   partial class DataTableView {
     23  partial class DataTableControl {
    2424    /// <summary>
    2525    /// Required designer variable.
     
    4545    /// </summary>
    4646    private void InitializeComponent() {
     47      this.components = new System.ComponentModel.Container();
    4748      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
    4849      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
     
    5152      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
    5253      this.configureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    53       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
    5454      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
    5555      this.SuspendLayout();
    5656      //
    57       // nameTextBox
    58       //
    59       this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
    60       this.errorProvider.SetIconPadding(this.nameTextBox, 2);
    61       this.nameTextBox.Location = new System.Drawing.Point(55, 0);
    62       this.nameTextBox.Size = new System.Drawing.Size(279, 20);
    63       //
    64       // infoLabel
    65       //
    66       this.infoLabel.Location = new System.Drawing.Point(340, 3);
    67       //
    6857      // chart
    6958      //
    70       this.chart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    71                   | System.Windows.Forms.AnchorStyles.Left)
    72                   | System.Windows.Forms.AnchorStyles.Right)));
     59      this.chart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
     60            | System.Windows.Forms.AnchorStyles.Left)
     61            | System.Windows.Forms.AnchorStyles.Right)));
    7362      this.chart.BorderlineColor = System.Drawing.Color.Black;
    7463      this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
     
    8473      legend1.Name = "Default";
    8574      this.chart.Legends.Add(legend1);
    86       this.chart.Location = new System.Drawing.Point(0, 26);
     75      this.chart.Location = new System.Drawing.Point(0, 0);
    8776      this.chart.Name = "chart";
    8877      series1.ChartArea = "Default";
     
    9079      series1.Name = "Default";
    9180      this.chart.Series.Add(series1);
    92       this.chart.Size = new System.Drawing.Size(359, 248);
     81      this.chart.Size = new System.Drawing.Size(359, 274);
    9382      this.chart.TabIndex = 3;
    9483      this.chart.Text = "chart";
     
    10897      this.configureToolStripMenuItem.Click += new System.EventHandler(this.configureToolStripMenuItem_Click);
    10998      //
    110       // DataTableView
     99      // DataTableControl
    111100      //
    112       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    113101      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
    114102      this.Controls.Add(this.chart);
    115       this.Name = "DataTableView";
     103      this.Name = "DataTableControl";
    116104      this.Size = new System.Drawing.Size(359, 274);
    117       this.Controls.SetChildIndex(this.infoLabel, 0);
    118       this.Controls.SetChildIndex(this.chart, 0);
    119       this.Controls.SetChildIndex(this.nameLabel, 0);
    120       this.Controls.SetChildIndex(this.nameTextBox, 0);
    121       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
    122105      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
    123106      this.ResumeLayout(false);
    124       this.PerformLayout();
    125107
    126108    }
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableControl.cs

    r14438 r14439  
    2727using System.Windows.Forms.DataVisualization.Charting;
    2828using HeuristicLab.Collections;
    29 using HeuristicLab.Core.Views;
    30 using HeuristicLab.MainForm;
    3129
    3230namespace HeuristicLab.Analysis.Views {
    33   [View("DataTable View")]
    34   [Content(typeof(DataTable), true)]
    35   public partial class DataTableView : NamedItemView, IConfigureableView {
     31  public partial class DataTableControl : UserControl {
    3632    protected List<Series> invisibleSeries;
    3733    protected Dictionary<IObservableList<double>, DataRow> valuesRowsTable;
    3834
    39     public new DataTable Content {
    40       get { return (DataTable)base.Content; }
    41       set { base.Content = value; }
    42     }
    43 
    44     public DataTableView() {
     35    private DataTable content;
     36    public DataTable Content {
     37      get { return content; }
     38      set {
     39        if (value == content) return;
     40        if (content != null) DeregisterContentEvents();
     41        content = value;
     42        if (content != null) RegisterContentEvents();
     43        OnContentChanged();
     44        SetEnabledStateOfControls();
     45      }
     46    }
     47
     48    public DataTableControl() {
    4549      InitializeComponent();
    4650      valuesRowsTable = new Dictionary<IObservableList<double>, DataRow>();
     
    5256
    5357    #region Event Handler Registration
    54     protected override void DeregisterContentEvents() {
     58    protected virtual void DeregisterContentEvents() {
    5559      foreach (DataRow row in Content.Rows)
    5660        DeregisterDataRowEvents(row);
     
    6064      Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsReplaced);
    6165      Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<DataRow>(Rows_CollectionReset);
    62       base.DeregisterContentEvents();
    63     }
    64     protected override void RegisterContentEvents() {
    65       base.RegisterContentEvents();
     66    }
     67    protected virtual void RegisterContentEvents() {
    6668      Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);
    6769      Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsAdded);
     
    9395    #endregion
    9496
    95     protected override void OnContentChanged() {
    96       base.OnContentChanged();
     97    protected virtual void OnContentChanged() {
    9798      invisibleSeries.Clear();
    9899      chart.Titles[0].Text = string.Empty;
     
    110111    }
    111112
    112     protected override void SetEnabledStateOfControls() {
    113       base.SetEnabledStateOfControls();
     113    protected virtual void SetEnabledStateOfControls() {
    114114      chart.Enabled = Content != null;
    115115    }
     
    284284    #region Event Handlers
    285285    #region Content Event Handlers
    286     protected override void Content_NameChanged(object sender, EventArgs e) {
    287       if (InvokeRequired)
    288         Invoke(new EventHandler(Content_NameChanged), sender, e);
    289       else {
    290         chart.Titles[0].Text = Content.Name;
    291         chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.Name);
    292         base.Content_NameChanged(sender, e);
    293       }
    294     }
    295286    private void Content_VisualPropertiesChanged(object sender, EventArgs e) {
    296287      if (InvokeRequired)
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.Designer.cs

    r14435 r14439  
    4545    /// </summary>
    4646    private void InitializeComponent() {
    47       System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
    48       System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
    49       System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
    50       System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
    51       this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
    52       this.configureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
     47      this.chart = new HeuristicLab.Analysis.Views.DataTableControl();
    5348      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
    54       ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
    5549      this.SuspendLayout();
    5650      //
     
    7165                  | System.Windows.Forms.AnchorStyles.Left)
    7266                  | System.Windows.Forms.AnchorStyles.Right)));
    73       this.chart.BorderlineColor = System.Drawing.Color.Black;
    74       this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
    75       chartArea1.AxisX.Minimum = 0D;
    76       chartArea1.CursorX.IsUserEnabled = true;
    77       chartArea1.CursorX.IsUserSelectionEnabled = true;
    78       chartArea1.CursorY.IsUserEnabled = true;
    79       chartArea1.CursorY.IsUserSelectionEnabled = true;
    80       chartArea1.Name = "Default";
    81       this.chart.ChartAreas.Add(chartArea1);
    82       legend1.Alignment = System.Drawing.StringAlignment.Center;
    83       legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
    84       legend1.Name = "Default";
    85       this.chart.Legends.Add(legend1);
    8667      this.chart.Location = new System.Drawing.Point(0, 26);
    8768      this.chart.Name = "chart";
    88       series1.ChartArea = "Default";
    89       series1.Legend = "Default";
    90       series1.Name = "Default";
    91       this.chart.Series.Add(series1);
    9269      this.chart.Size = new System.Drawing.Size(359, 248);
    9370      this.chart.TabIndex = 3;
    9471      this.chart.Text = "chart";
    95       title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
    96       title1.Name = "Default";
    97       title1.Text = "Title";
    98       this.chart.Titles.Add(title1);
    99       this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
    100       this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
    101       this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
    102       //
    103       // configureToolStripMenuItem
    104       //
    105       this.configureToolStripMenuItem.Name = "configureToolStripMenuItem";
    106       this.configureToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
    107       this.configureToolStripMenuItem.Text = "Configure Chart";
    108       this.configureToolStripMenuItem.Click += new System.EventHandler(this.configureToolStripMenuItem_Click);
    10972      //
    11073      // DataTableView
     
    12083      this.Controls.SetChildIndex(this.nameTextBox, 0);
    12184      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
    122       ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
    12385      this.ResumeLayout(false);
    12486      this.PerformLayout();
    125 
    12687    }
    12788
    12889    #endregion
    12990
    130     protected HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
    131     private System.Windows.Forms.ToolStripMenuItem configureToolStripMenuItem;
     91    protected HeuristicLab.Analysis.Views.DataTableControl chart;
    13292  }
    13393}
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.cs

    r14438 r14439  
    2121
    2222using System;
    23 using System.Collections.Generic;
    24 using System.Drawing;
    25 using System.Linq;
    26 using System.Windows.Forms;
    27 using System.Windows.Forms.DataVisualization.Charting;
    28 using HeuristicLab.Collections;
    2923using HeuristicLab.Core.Views;
    3024using HeuristicLab.MainForm;
     
    3428  [Content(typeof(DataTable), true)]
    3529  public partial class DataTableView : NamedItemView, IConfigureableView {
    36     protected List<Series> invisibleSeries;
    37     protected Dictionary<IObservableList<double>, DataRow> valuesRowsTable;
    3830
    3931    public new DataTable Content {
     
    4436    public DataTableView() {
    4537      InitializeComponent();
    46       valuesRowsTable = new Dictionary<IObservableList<double>, DataRow>();
    47       invisibleSeries = new List<Series>();
    48       chart.CustomizeAllChartAreas();
    49       chart.ChartAreas[0].CursorX.Interval = 1;
    50       chart.ContextMenuStrip.Items.Add(configureToolStripMenuItem);
    5138    }
    52 
    53     #region Event Handler Registration
    54     protected override void DeregisterContentEvents() {
    55       foreach (DataRow row in Content.Rows)
    56         DeregisterDataRowEvents(row);
    57       Content.VisualPropertiesChanged -= new EventHandler(Content_VisualPropertiesChanged);
    58       Content.Rows.ItemsAdded -= new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsAdded);
    59       Content.Rows.ItemsRemoved -= new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsRemoved);
    60       Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsReplaced);
    61       Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<DataRow>(Rows_CollectionReset);
    62       base.DeregisterContentEvents();
    63     }
    64     protected override void RegisterContentEvents() {
    65       base.RegisterContentEvents();
    66       Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);
    67       Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsAdded);
    68       Content.Rows.ItemsRemoved += new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsRemoved);
    69       Content.Rows.ItemsReplaced += new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsReplaced);
    70       Content.Rows.CollectionReset += new CollectionItemsChangedEventHandler<DataRow>(Rows_CollectionReset);
    71     }
    72 
    73     protected virtual void RegisterDataRowEvents(DataRow row) {
    74       row.NameChanged += new EventHandler(Row_NameChanged);
    75       row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
    76       valuesRowsTable.Add(row.Values, row);
    77       row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
    78       row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
    79       row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
    80       row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
    81       row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
    82     }
    83     protected virtual void DeregisterDataRowEvents(DataRow row) {
    84       row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
    85       row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
    86       row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
    87       row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
    88       row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
    89       valuesRowsTable.Remove(row.Values);
    90       row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);
    91       row.NameChanged -= new EventHandler(Row_NameChanged);
    92     }
    93     #endregion
    9439
    9540    protected override void OnContentChanged() {
    9641      base.OnContentChanged();
    97       invisibleSeries.Clear();
    98       chart.Titles[0].Text = string.Empty;
    99       chart.ChartAreas[0].AxisX.Title = string.Empty;
    100       chart.ChartAreas[0].AxisY.Title = string.Empty;
    101       chart.ChartAreas[0].AxisY2.Title = string.Empty;
    102       chart.Series.Clear();
    103       if (Content != null) {
    104         chart.Titles[0].Text = Content.Name;
    105         chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.Name);
    106         AddDataRows(Content.Rows);
    107         ConfigureChartArea(chart.ChartAreas[0]);
    108         RecalculateAxesScale(chart.ChartAreas[0]);
    109       }
     42      chart.Content = Content;
    11043    }
    11144
     
    11548    }
    11649
    117     public void ShowConfiguration() {
    118       if (Content != null) {
    119         using (var dialog = new DataTableVisualPropertiesDialog(Content)) {
    120           dialog.ShowDialog(this);
    121         }
    122       } else MessageBox.Show("Nothing to configure.");
    123     }
    124     protected virtual void AddDataRows(IEnumerable<DataRow> rows) {
    125       foreach (var row in rows) {
    126         RegisterDataRowEvents(row);
    127         var series = new Series(row.Name);
    128         if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
    129         else series.LegendText = row.Name;
    130         ConfigureSeries(series, row);
    131         FillSeriesWithRowValues(series, row);
    132         chart.Series.Add(series);
    133       }
    134       ConfigureChartArea(chart.ChartAreas[0]);
    135       RecalculateAxesScale(chart.ChartAreas[0]);
    136       UpdateYCursorInterval();
    137     }
    138 
    139     protected virtual void RemoveDataRows(IEnumerable<DataRow> rows) {
    140       foreach (var row in rows) {
    141         DeregisterDataRowEvents(row);
    142         Series series = chart.Series[row.Name];
    143         chart.Series.Remove(series);
    144         if (invisibleSeries.Contains(series))
    145           invisibleSeries.Remove(series);
    146       }
    147       RecalculateAxesScale(chart.ChartAreas[0]);
    148     }
    149 
    150     private void ConfigureSeries(Series series, DataRow row) {
    151       RemoveCustomPropertyIfExists(series, "PointWidth");
    152       series.BorderWidth = 1;
    153       series.BorderDashStyle = ChartDashStyle.Solid;
    154       series.BorderColor = Color.Empty;
    155 
    156       if (row.VisualProperties.Color != Color.Empty)
    157         series.Color = row.VisualProperties.Color;
    158       else series.Color = Color.Empty;
    159       series.IsVisibleInLegend = row.VisualProperties.IsVisibleInLegend;
    160 
    161       switch (row.VisualProperties.ChartType) {
    162         case DataRowVisualProperties.DataRowChartType.Line:
    163           series.ChartType = SeriesChartType.FastLine;
    164           series.BorderWidth = row.VisualProperties.LineWidth;
    165           series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
    166           break;
    167         case DataRowVisualProperties.DataRowChartType.Bars:
    168           // Bar is incompatible with anything but Bar and StackedBar*
    169           if (!chart.Series.Any(x => x.ChartType != SeriesChartType.Bar && x.ChartType != SeriesChartType.StackedBar && x.ChartType != SeriesChartType.StackedBar100))
    170             series.ChartType = SeriesChartType.Bar;
    171           else {
    172             series.ChartType = SeriesChartType.FastPoint; //default
    173             row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
    174           }
    175           break;
    176         case DataRowVisualProperties.DataRowChartType.Columns:
    177           series.ChartType = SeriesChartType.Column;
    178           break;
    179         case DataRowVisualProperties.DataRowChartType.Points:
    180           series.ChartType = SeriesChartType.FastPoint;
    181           break;
    182         case DataRowVisualProperties.DataRowChartType.Histogram:
    183           series.ChartType = SeriesChartType.Column;
    184           series.SetCustomProperty("PointWidth", "1");
    185           if (!series.Color.IsEmpty && series.Color.GetBrightness() < 0.25)
    186             series.BorderColor = Color.White;
    187           else series.BorderColor = Color.Black;
    188           break;
    189         case DataRowVisualProperties.DataRowChartType.StepLine:
    190           series.ChartType = SeriesChartType.StepLine;
    191           series.BorderWidth = row.VisualProperties.LineWidth;
    192           series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
    193           break;
    194         default:
    195           series.ChartType = SeriesChartType.FastPoint;
    196           break;
    197       }
    198       series.YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary;
    199       series.XAxisType = row.VisualProperties.SecondXAxis ? AxisType.Secondary : AxisType.Primary;
    200       if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
    201       else series.LegendText = row.Name;
    202 
    203       string xAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.XAxisTitle)
    204                       ? "X"
    205                       : Content.VisualProperties.XAxisTitle;
    206       string yAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.YAxisTitle)
    207                             ? "Y"
    208                             : Content.VisualProperties.YAxisTitle;
    209       series.ToolTip =
    210         series.LegendText + Environment.NewLine +
    211         xAxisTitle + " = " + "#INDEX," + Environment.NewLine +
    212         yAxisTitle + " = " + "#VAL";
    213     }
    214 
    215     private void ConfigureChartArea(ChartArea area) {
    216       if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;
    217       if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;
    218       chart.Titles[0].Text = Content.VisualProperties.Title;
    219       chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.VisualProperties.Title);
    220 
    221       if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;
    222       if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor;
    223       area.AxisX.Title = Content.VisualProperties.XAxisTitle;
    224 
    225       if (Content.VisualProperties.AxisTitleFont != null) area.AxisX2.TitleFont = Content.VisualProperties.AxisTitleFont;
    226       if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX2.TitleForeColor = Content.VisualProperties.AxisTitleColor;
    227       area.AxisX2.Title = Content.VisualProperties.SecondXAxisTitle;
    228 
    229       if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont;
    230       if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor;
    231       area.AxisY.Title = Content.VisualProperties.YAxisTitle;
    232 
    233       if (Content.VisualProperties.AxisTitleFont != null) area.AxisY2.TitleFont = Content.VisualProperties.AxisTitleFont;
    234       if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY2.TitleForeColor = Content.VisualProperties.AxisTitleColor;
    235       area.AxisY2.Title = Content.VisualProperties.SecondYAxisTitle;
    236 
    237       area.AxisX.IsLogarithmic = Content.VisualProperties.XAxisLogScale;
    238       area.AxisX2.IsLogarithmic = Content.VisualProperties.SecondXAxisLogScale;
    239       area.AxisY.IsLogarithmic = Content.VisualProperties.YAxisLogScale;
    240       area.AxisY2.IsLogarithmic = Content.VisualProperties.SecondYAxisLogScale;
    241     }
    242 
    243     private void RecalculateAxesScale(ChartArea area) {
    244       // Reset the axes bounds so that RecalculateAxesScale() will assign new bounds
    245       foreach (Axis a in area.Axes) {
    246         a.Minimum = double.NaN;
    247         a.Maximum = double.NaN;
    248       }
    249       area.RecalculateAxesScale();
    250       area.AxisX.IsMarginVisible = false;
    251       area.AxisX2.IsMarginVisible = false;
    252 
    253       if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue;
    254       if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue;
    255       if (!Content.VisualProperties.SecondXAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMinimumFixedValue)) area.AxisX2.Minimum = Content.VisualProperties.SecondXAxisMinimumFixedValue;
    256       if (!Content.VisualProperties.SecondXAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMaximumFixedValue)) area.AxisX2.Maximum = Content.VisualProperties.SecondXAxisMaximumFixedValue;
    257       if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue;
    258       if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue;
    259       if (!Content.VisualProperties.SecondYAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMinimumFixedValue)) area.AxisY2.Minimum = Content.VisualProperties.SecondYAxisMinimumFixedValue;
    260       if (!Content.VisualProperties.SecondYAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMaximumFixedValue)) area.AxisY2.Maximum = Content.VisualProperties.SecondYAxisMaximumFixedValue;
    261       if (area.AxisX.Minimum >= area.AxisX.Maximum) area.AxisX.Maximum = area.AxisX.Minimum + 1;
    262       if (area.AxisX2.Minimum >= area.AxisX2.Maximum) area.AxisX2.Maximum = area.AxisX2.Minimum + 1;
    263       if (area.AxisY.Minimum >= area.AxisY.Maximum) area.AxisY.Maximum = area.AxisY.Minimum + 1;
    264       if (area.AxisY2.Minimum >= area.AxisY2.Maximum) area.AxisY2.Maximum = area.AxisY2.Minimum + 1;
    265     }
    266 
    267     protected virtual void UpdateYCursorInterval() {
    268       double interestingValuesRange = (
    269         from series in chart.Series
    270         where series.Enabled
    271         let values = (from point in series.Points
    272                       where !point.IsEmpty
    273                       select point.YValues[0]).DefaultIfEmpty(1.0)
    274         let range = values.Max() - values.Min()
    275         where range > 0.0
    276         select range
    277         ).DefaultIfEmpty(1.0).Min();
    278 
    279       double digits = (int)Math.Log10(interestingValuesRange) - 3;
    280       double yZoomInterval = Math.Pow(10, digits);
    281       this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
    282     }
    283 
    284     #region Event Handlers
    28550    #region Content Event Handlers
    28651    protected override void Content_NameChanged(object sender, EventArgs e) {
     
    28853        Invoke(new EventHandler(Content_NameChanged), sender, e);
    28954      else {
    290         chart.Titles[0].Text = Content.Name;
    291         chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.Name);
     55        Content.VisualProperties.Title = Content.Name;
    29256        base.Content_NameChanged(sender, e);
    293       }
    294     }
    295     private void Content_VisualPropertiesChanged(object sender, EventArgs e) {
    296       if (InvokeRequired)
    297         Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e);
    298       else {
    299         ConfigureChartArea(chart.ChartAreas[0]);
    300         RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed
    301       }
    302     }
    303     #endregion
    304     #region Rows Event Handlers
    305     private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
    306       if (InvokeRequired)
    307         Invoke(new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsAdded), sender, e);
    308       else {
    309         AddDataRows(e.Items);
    310       }
    311     }
    312     private void Rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
    313       if (InvokeRequired)
    314         Invoke(new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsRemoved), sender, e);
    315       else {
    316         RemoveDataRows(e.Items);
    317       }
    318     }
    319     private void Rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
    320       if (InvokeRequired)
    321         Invoke(new CollectionItemsChangedEventHandler<DataRow>(Rows_ItemsReplaced), sender, e);
    322       else {
    323         RemoveDataRows(e.OldItems);
    324         AddDataRows(e.Items);
    325       }
    326     }
    327     private void Rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
    328       if (InvokeRequired)
    329         Invoke(new CollectionItemsChangedEventHandler<DataRow>(Rows_CollectionReset), sender, e);
    330       else {
    331         RemoveDataRows(e.OldItems);
    332         AddDataRows(e.Items);
    333       }
    334     }
    335     #endregion
    336     #region Row Event Handlers
    337     private void Row_VisualPropertiesChanged(object sender, EventArgs e) {
    338       if (InvokeRequired)
    339         Invoke(new EventHandler(Row_VisualPropertiesChanged), sender, e);
    340       else {
    341         DataRow row = (DataRow)sender;
    342         Series series = chart.Series[row.Name];
    343         series.Points.Clear();
    344         ConfigureSeries(series, row);
    345         FillSeriesWithRowValues(series, row);
    346         RecalculateAxesScale(chart.ChartAreas[0]);
    347       }
    348     }
    349     private void Row_NameChanged(object sender, EventArgs e) {
    350       if (InvokeRequired)
    351         Invoke(new EventHandler(Row_NameChanged), sender, e);
    352       else {
    353         DataRow row = (DataRow)sender;
    354         chart.Series[row.Name].Name = row.Name;
    355       }
    356     }
    357     #endregion
    358     #region Values Event Handlers
    359     private void Values_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
    360       if (InvokeRequired)
    361         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded), sender, e);
    362       else {
    363         DataRow row = null;
    364         valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
    365         if (row != null) {
    366           Series rowSeries = chart.Series[row.Name];
    367           if (!invisibleSeries.Contains(rowSeries)) {
    368             rowSeries.Points.Clear();
    369             FillSeriesWithRowValues(rowSeries, row);
    370             RecalculateAxesScale(chart.ChartAreas[0]);
    371             UpdateYCursorInterval();
    372           }
    373         }
    374       }
    375     }
    376     private void Values_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
    377       if (InvokeRequired)
    378         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved), sender, e);
    379       else {
    380         DataRow row = null;
    381         valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
    382         if (row != null) {
    383           Series rowSeries = chart.Series[row.Name];
    384           if (!invisibleSeries.Contains(rowSeries)) {
    385             rowSeries.Points.Clear();
    386             FillSeriesWithRowValues(rowSeries, row);
    387             RecalculateAxesScale(chart.ChartAreas[0]);
    388             UpdateYCursorInterval();
    389           }
    390         }
    391       }
    392     }
    393     private void Values_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
    394       if (InvokeRequired)
    395         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced), sender, e);
    396       else {
    397         DataRow row = null;
    398         valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
    399         if (row != null) {
    400           Series rowSeries = chart.Series[row.Name];
    401           if (!invisibleSeries.Contains(rowSeries)) {
    402             if (row.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram) {
    403               rowSeries.Points.Clear();
    404               FillSeriesWithRowValues(rowSeries, row);
    405             } else {
    406               foreach (IndexedItem<double> item in e.Items) {
    407                 if (IsInvalidValue(item.Value))
    408                   rowSeries.Points[item.Index].IsEmpty = true;
    409                 else {
    410                   rowSeries.Points[item.Index].YValues = new double[] { item.Value };
    411                   rowSeries.Points[item.Index].IsEmpty = false;
    412                 }
    413               }
    414             }
    415             RecalculateAxesScale(chart.ChartAreas[0]);
    416             UpdateYCursorInterval();
    417           }
    418         }
    419       }
    420     }
    421     private void Values_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
    422       if (InvokeRequired)
    423         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved), sender, e);
    424       else {
    425         DataRow row = null;
    426         valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
    427         if (row != null) {
    428           Series rowSeries = chart.Series[row.Name];
    429           if (!invisibleSeries.Contains(rowSeries)) {
    430             rowSeries.Points.Clear();
    431             FillSeriesWithRowValues(rowSeries, row);
    432             RecalculateAxesScale(chart.ChartAreas[0]);
    433             UpdateYCursorInterval();
    434           }
    435         }
    436       }
    437     }
    438 
    439     private void Values_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
    440       if (InvokeRequired)
    441         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset), sender, e);
    442       else {
    443         DataRow row = null;
    444         valuesRowsTable.TryGetValue((IObservableList<double>)sender, out row);
    445         if (row != null) {
    446           Series rowSeries = chart.Series[row.Name];
    447           if (!invisibleSeries.Contains(rowSeries)) {
    448             rowSeries.Points.Clear();
    449             FillSeriesWithRowValues(rowSeries, row);
    450             RecalculateAxesScale(chart.ChartAreas[0]);
    451             UpdateYCursorInterval();
    452           }
    453         }
    454       }
    455     }
    456     #endregion
    457     private void configureToolStripMenuItem_Click(object sender, EventArgs e) {
    458       ShowConfiguration();
    459     }
    460     #endregion
    461 
    462     #region Chart Event Handlers
    463     private void chart_MouseDown(object sender, MouseEventArgs e) {
    464       HitTestResult result = chart.HitTest(e.X, e.Y);
    465       if (result.ChartElementType == ChartElementType.LegendItem) {
    466         ToggleSeriesVisible(result.Series);
    467       }
    468     }
    469     private void chart_MouseMove(object sender, MouseEventArgs e) {
    470       HitTestResult result = chart.HitTest(e.X, e.Y);
    471       if (result.ChartElementType == ChartElementType.LegendItem)
    472         this.Cursor = Cursors.Hand;
    473       else
    474         this.Cursor = Cursors.Default;
    475     }
    476     private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
    477       foreach (LegendItem legendItem in e.LegendItems) {
    478         var series = chart.Series[legendItem.SeriesName];
    479         if (series != null) {
    480           bool seriesIsInvisible = invisibleSeries.Contains(series);
    481           foreach (LegendCell cell in legendItem.Cells) {
    482             cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
    483           }
    484         }
    48557      }
    48658    }
    48759    #endregion
    48860
    489     private void ToggleSeriesVisible(Series series) {
    490       if (!invisibleSeries.Contains(series)) {
    491         series.Points.Clear();
    492         invisibleSeries.Add(series);
    493       } else {
    494         invisibleSeries.Remove(series);
    495         if (Content != null) {
    496 
    497           var row = (from r in Content.Rows
    498                      where r.Name == series.Name
    499                      select r).Single();
    500           FillSeriesWithRowValues(series, row);
    501           this.chart.Legends[series.Legend].ForeColor = Color.Black;
    502           RecalculateAxesScale(chart.ChartAreas[0]);
    503           UpdateYCursorInterval();
    504         }
    505       }
     61    public void ShowConfiguration() {
     62      chart.ShowConfiguration();
    50663    }
    507 
    508     private void FillSeriesWithRowValues(Series series, DataRow row) {
    509       switch (row.VisualProperties.ChartType) {
    510         case DataRowVisualProperties.DataRowChartType.Histogram:
    511           CalculateHistogram(series, row);
    512           break;
    513         default: {
    514             bool yLogarithmic = series.YAxisType == AxisType.Primary
    515                                   ? Content.VisualProperties.YAxisLogScale
    516                                   : Content.VisualProperties.SecondYAxisLogScale;
    517             bool xLogarithmic = series.XAxisType == AxisType.Primary
    518                                   ? Content.VisualProperties.XAxisLogScale
    519                                   : Content.VisualProperties.SecondXAxisLogScale;
    520             for (int i = 0; i < row.Values.Count; i++) {
    521               var value = row.Values[i];
    522               var point = new DataPoint();
    523               point.XValue = row.VisualProperties.StartIndexZero && !xLogarithmic ? i : i + 1;
    524               if (IsInvalidValue(value) || (yLogarithmic && value <= 0))
    525                 point.IsEmpty = true;
    526               else
    527                 point.YValues = new double[] { value };
    528               series.Points.Add(point);
    529             }
    530           }
    531           break;
    532       }
    533     }
    534 
    535     protected virtual void CalculateHistogram(Series series, DataRow row) {
    536       series.Points.Clear();
    537       if (!row.Values.Any()) return;
    538       int bins = row.VisualProperties.Bins;
    539 
    540       double minValue = row.Values.Min();
    541       double maxValue = row.Values.Max();
    542       double intervalWidth = (maxValue - minValue) / bins;
    543       if (intervalWidth < 0) return;
    544       if (intervalWidth == 0) {
    545         series.Points.AddXY(minValue, row.Values.Count);
    546         return;
    547       }
    548 
    549       if (!row.VisualProperties.ExactBins) {
    550         intervalWidth = HumanRoundRange(intervalWidth);
    551         minValue = Math.Floor(minValue / intervalWidth) * intervalWidth;
    552         maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth;
    553       }
    554 
    555       double intervalCenter = intervalWidth / 2;
    556 
    557       double min = 0.0, max = 0.0;
    558       if (!Double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue) && !Content.VisualProperties.XAxisMinimumAuto)
    559         min = Content.VisualProperties.XAxisMinimumFixedValue;
    560       else min = minValue;
    561       if (!Double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue) && !Content.VisualProperties.XAxisMaximumAuto)
    562         max = Content.VisualProperties.XAxisMaximumFixedValue;
    563       else max = maxValue + intervalWidth;
    564 
    565       double axisInterval = intervalWidth / row.VisualProperties.ScaleFactor;
    566 
    567       var area = chart.ChartAreas[0];
    568       area.AxisX.Interval = axisInterval;
    569 
    570       series.SetCustomProperty("PointWidth", "1"); // 0.8 is the default value
    571 
    572       // get the range or intervals which define the grouping of the frequency values
    573       var doubleRange = DoubleRange(min, max, intervalWidth).Skip(1).ToList();
    574 
    575       // aggregate the row values by unique key and frequency value
    576       var valueFrequencies = (from v in row.Values
    577                               where !IsInvalidValue(v)
    578                               orderby v
    579                               group v by v into g
    580                               select new Tuple<double, double>(g.First(), g.Count())).ToList();
    581 
    582       // shift the chart to the left so the bars are placed on the intervals
    583       if (valueFrequencies.First().Item1 < doubleRange.First())
    584         series.Points.Add(new DataPoint(min - intervalWidth, 0));
    585 
    586       // add data points
    587       int j = 0;
    588       foreach (var d in doubleRange) {
    589         double sum = 0.0;
    590         // sum the frequency values that fall within the same interval
    591         while (j < valueFrequencies.Count && valueFrequencies[j].Item1 < d) {
    592           sum += valueFrequencies[j].Item2;
    593           ++j;
    594         }
    595         string xAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.XAxisTitle)
    596                               ? "X"
    597                               : Content.VisualProperties.XAxisTitle;
    598         string yAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.YAxisTitle)
    599                               ? "Y"
    600                               : Content.VisualProperties.YAxisTitle;
    601         series.Points.Add(new DataPoint(d - intervalCenter, sum) {
    602           ToolTip =
    603             xAxisTitle + ": [" + (d - intervalWidth) + "-" + d + ")" + Environment.NewLine +
    604             yAxisTitle + ": " + sum
    605         });
    606       }
    607     }
    608 
    609     #region Helpers
    610     public static IEnumerable<double> DoubleRange(double min, double max, double step) {
    611       double i;
    612       for (i = min; i <= max; i += step)
    613         yield return i;
    614 
    615       if (i != max + step)
    616         yield return i;
    617     }
    618 
    619     protected void RemoveCustomPropertyIfExists(Series series, string property) {
    620       if (series.IsCustomPropertySet(property)) series.DeleteCustomProperty(property);
    621     }
    622 
    623     private double HumanRoundRange(double range) {
    624       double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range)));
    625       double rounding = range / base10;
    626       if (rounding <= 1.5) rounding = 1;
    627       else if (rounding <= 2.25) rounding = 2;
    628       else if (rounding <= 3.75) rounding = 2.5;
    629       else if (rounding <= 7.5) rounding = 5;
    630       else rounding = 10;
    631       return rounding * base10;
    632     }
    633 
    634     private double HumanRoundMax(double max) {
    635       double base10;
    636       if (max > 0) base10 = Math.Pow(10.0, Math.Floor(Math.Log10(max)));
    637       else base10 = Math.Pow(10.0, Math.Ceiling(Math.Log10(-max)));
    638       double rounding = (max > 0) ? base10 : -base10;
    639       while (rounding < max) rounding += base10;
    640       return rounding;
    641     }
    642 
    643     private ChartDashStyle ConvertLineStyle(DataRowVisualProperties.DataRowLineStyle dataRowLineStyle) {
    644       switch (dataRowLineStyle) {
    645         case DataRowVisualProperties.DataRowLineStyle.Dash:
    646           return ChartDashStyle.Dash;
    647         case DataRowVisualProperties.DataRowLineStyle.DashDot:
    648           return ChartDashStyle.DashDot;
    649         case DataRowVisualProperties.DataRowLineStyle.DashDotDot:
    650           return ChartDashStyle.DashDotDot;
    651         case DataRowVisualProperties.DataRowLineStyle.Dot:
    652           return ChartDashStyle.Dot;
    653         case DataRowVisualProperties.DataRowLineStyle.NotSet:
    654           return ChartDashStyle.NotSet;
    655         case DataRowVisualProperties.DataRowLineStyle.Solid:
    656           return ChartDashStyle.Solid;
    657         default:
    658           return ChartDashStyle.NotSet;
    659       }
    660     }
    661 
    662     protected static bool IsInvalidValue(double x) {
    663       return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;
    664     }
    665     #endregion
    66664  }
    66765}
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj

    r14208 r14439  
    122122  </ItemGroup>
    123123  <ItemGroup>
     124    <Compile Include="DataTableControl.cs">
     125      <SubType>UserControl</SubType>
     126    </Compile>
     127    <Compile Include="DataTableControl.Designer.cs">
     128      <DependentUpon>DataTableControl.cs</DependentUpon>
     129    </Compile>
    124130    <Compile Include="IndexedDataTableView.cs">
    125131      <SubType>UserControl</SubType>
     
    127133    <Compile Include="IndexedDataTableView.Designer.cs">
    128134      <DependentUpon>IndexedDataTableView.cs</DependentUpon>
     135    </Compile>
     136    <Compile Include="ScatterPlotControl.cs">
     137      <SubType>UserControl</SubType>
     138    </Compile>
     139    <Compile Include="ScatterPlotControl.Designer.cs">
     140      <DependentUpon>ScatterPlotControl.cs</DependentUpon>
    129141    </Compile>
    130142    <Compile Include="ScatterPlotVisualPropertiesDialog.cs">
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotControl.Designer.cs

    r14435 r14439  
    2121
    2222namespace HeuristicLab.Analysis.Views {
    23   partial class ScatterPlotView {
     23  partial class ScatterPlotControl {
    2424    /// <summary>
    2525    /// Required designer variable.
     
    4545    /// </summary>
    4646    private void InitializeComponent() {
     47      this.components = new System.ComponentModel.Container();
    4748      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
    4849      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
     
    5152      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
    5253      this.configureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    53       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
    5454      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
    5555      this.SuspendLayout();
    5656      //
    57       // nameTextBox
    58       //
    59       this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
    60       this.errorProvider.SetIconPadding(this.nameTextBox, 2);
    61       this.nameTextBox.Location = new System.Drawing.Point(55, 0);
    62       this.nameTextBox.Size = new System.Drawing.Size(279, 20);
    63       //
    64       // infoLabel
    65       //
    66       this.infoLabel.Location = new System.Drawing.Point(340, 3);
    67       //
    6857      // chart
    6958      //
    70       this.chart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    71                   | System.Windows.Forms.AnchorStyles.Left)
    72                   | System.Windows.Forms.AnchorStyles.Right)));
     59      this.chart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
     60            | System.Windows.Forms.AnchorStyles.Left)
     61            | System.Windows.Forms.AnchorStyles.Right)));
    7362      this.chart.BorderlineColor = System.Drawing.Color.Black;
    7463      this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
     
    8473      legend1.Name = "Default";
    8574      this.chart.Legends.Add(legend1);
    86       this.chart.Location = new System.Drawing.Point(0, 26);
     75      this.chart.Location = new System.Drawing.Point(0, 0);
    8776      this.chart.Name = "chart";
    8877      series1.ChartArea = "Default";
     
    9079      series1.Name = "Default";
    9180      this.chart.Series.Add(series1);
    92       this.chart.Size = new System.Drawing.Size(359, 248);
     81      this.chart.Size = new System.Drawing.Size(359, 274);
    9382      this.chart.TabIndex = 3;
    9483      this.chart.Text = "chart";
     
    10695      this.configureToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
    10796      this.configureToolStripMenuItem.Text = "Configure Chart";
    108       this.configureToolStripMenuItem.Click += new System.EventHandler(configureToolStripMenuItem_Click);
     97      this.configureToolStripMenuItem.Click += new System.EventHandler(this.configureToolStripMenuItem_Click);
    10998      //
    110       // ScatterPlotView
     99      // ScatterPlotControl
    111100      //
    112       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    113101      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
    114102      this.Controls.Add(this.chart);
    115       this.Name = "ScatterPlotView";
     103      this.Name = "ScatterPlotControl";
    116104      this.Size = new System.Drawing.Size(359, 274);
    117       this.Controls.SetChildIndex(this.infoLabel, 0);
    118       this.Controls.SetChildIndex(this.chart, 0);
    119       this.Controls.SetChildIndex(this.nameLabel, 0);
    120       this.Controls.SetChildIndex(this.nameTextBox, 0);
    121       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
    122105      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
    123106      this.ResumeLayout(false);
    124       this.PerformLayout();
    125107
    126108    }
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotControl.cs

    r14438 r14439  
    2828using HeuristicLab.Collections;
    2929using HeuristicLab.Common;
    30 using HeuristicLab.Core.Views;
    31 using HeuristicLab.MainForm;
    3230
    3331namespace HeuristicLab.Analysis.Views {
    34   [View("ScatterPlot View")]
    35   [Content(typeof(ScatterPlot), true)]
    36   public partial class ScatterPlotView : NamedItemView, IConfigureableView {
     32  public partial class ScatterPlotControl : UserControl {
    3733    protected List<Series> invisibleSeries;
    3834    protected Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow> pointsRowsTable;
    3935    private double xMin, xMax, yMin, yMax;
    4036
    41     public new ScatterPlot Content {
    42       get { return (ScatterPlot)base.Content; }
    43       set { base.Content = value; }
    44     }
    45 
    46     public ScatterPlotView() {
     37    private ScatterPlot content;
     38    public ScatterPlot Content {
     39      get { return content; }
     40      set {
     41        if (value == content) return;
     42        if (content != null) DeregisterContentEvents();
     43        content = value;
     44        if (content != null) RegisterContentEvents();
     45        OnContentChanged();
     46        SetEnabledStateOfControls();
     47      }
     48    }
     49
     50    public ScatterPlotControl() {
    4751      InitializeComponent();
    4852      pointsRowsTable = new Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow>();
     
    5458
    5559    #region Event Handler Registration
    56     protected override void DeregisterContentEvents() {
     60    protected virtual void DeregisterContentEvents() {
    5761      foreach (ScatterPlotDataRow row in Content.Rows)
    5862        DeregisterScatterPlotDataRowEvents(row);
     
    6266      Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);
    6367      Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);
    64       base.DeregisterContentEvents();
    65     }
    66     protected override void RegisterContentEvents() {
    67       base.RegisterContentEvents();
     68    }
     69    protected virtual void RegisterContentEvents() {
    6870      Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);
    6971      Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);
     
    9395    #endregion
    9496
    95     protected override void OnContentChanged() {
    96       base.OnContentChanged();
     97    protected virtual void OnContentChanged() {
    9798      invisibleSeries.Clear();
    9899      chart.Titles[0].Text = string.Empty;
     
    110111    }
    111112
    112     protected override void SetEnabledStateOfControls() {
    113       base.SetEnabledStateOfControls();
     113    protected virtual void SetEnabledStateOfControls() {
    114114      chart.Enabled = Content != null;
    115115    }
     
    252252    #region Event Handlers
    253253    #region Content Event Handlers
    254     protected override void Content_NameChanged(object sender, EventArgs e) {
    255       if (InvokeRequired)
    256         Invoke(new EventHandler(Content_NameChanged), sender, e);
    257       else {
    258         chart.Titles[0].Text = Content.Name;
    259         chart.Titles[0].Visible = !string.IsNullOrEmpty(Content.Name);
    260         base.Content_NameChanged(sender, e);
    261       }
    262     }
    263254    private void Content_VisualPropertiesChanged(object sender, EventArgs e) {
    264255      if (InvokeRequired)
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.Designer.cs

    r14435 r14439  
    4545    /// </summary>
    4646    private void InitializeComponent() {
    47       System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
    48       System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
    49       System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
    50       System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
    51       this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
    52       this.configureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
     47      this.chart = new HeuristicLab.Analysis.Views.ScatterPlotControl();
    5348      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
    54       ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
    5549      this.SuspendLayout();
    5650      //
     
    7165                  | System.Windows.Forms.AnchorStyles.Left)
    7266                  | System.Windows.Forms.AnchorStyles.Right)));
    73       this.chart.BorderlineColor = System.Drawing.Color.Black;
    74       this.chart.BorderlineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Solid;
    75       chartArea1.AxisX.Minimum = 0D;
    76       chartArea1.CursorX.IsUserEnabled = true;
    77       chartArea1.CursorX.IsUserSelectionEnabled = true;
    78       chartArea1.CursorY.IsUserEnabled = true;
    79       chartArea1.CursorY.IsUserSelectionEnabled = true;
    80       chartArea1.Name = "Default";
    81       this.chart.ChartAreas.Add(chartArea1);
    82       legend1.Alignment = System.Drawing.StringAlignment.Center;
    83       legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
    84       legend1.Name = "Default";
    85       this.chart.Legends.Add(legend1);
    8667      this.chart.Location = new System.Drawing.Point(0, 26);
    8768      this.chart.Name = "chart";
    88       series1.ChartArea = "Default";
    89       series1.Legend = "Default";
    90       series1.Name = "Default";
    91       this.chart.Series.Add(series1);
    9269      this.chart.Size = new System.Drawing.Size(359, 248);
    9370      this.chart.TabIndex = 3;
    9471      this.chart.Text = "chart";
    95       title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
    96       title1.Name = "Default";
    97       title1.Text = "Title";
    98       this.chart.Titles.Add(title1);
    99       this.chart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
    100       this.chart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
    101       this.chart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
    102       //
    103       // configureToolStripMenuItem
    104       //
    105       this.configureToolStripMenuItem.Name = "configureToolStripMenuItem";
    106       this.configureToolStripMenuItem.Size = new System.Drawing.Size(256, 22);
    107       this.configureToolStripMenuItem.Text = "Configure Chart";
    108       this.configureToolStripMenuItem.Click += new System.EventHandler(configureToolStripMenuItem_Click);
    10972      //
    11073      // ScatterPlotView
     
    12083      this.Controls.SetChildIndex(this.nameTextBox, 0);
    12184      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
    122       ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
    12385      this.ResumeLayout(false);
    12486      this.PerformLayout();
     
    12789    #endregion
    12890
    129     protected HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
    130     private System.Windows.Forms.ToolStripMenuItem configureToolStripMenuItem;
     91    protected HeuristicLab.Analysis.Views.ScatterPlotControl chart;
    13192  }
    13293}
  • trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs

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