source: stable/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotMultiView.cs

Last change on this file was 17181, checked in by swagner, 3 years ago

#2875: Merged r17180 from trunk to stable

File size: 32.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.Windows.Forms;
27using HeuristicLab.Analysis;
28using HeuristicLab.Analysis.Views;
29using HeuristicLab.Collections;
30using HeuristicLab.Data;
31using HeuristicLab.MainForm;
32using HeuristicLab.MainForm.WindowsForms;
33using AggregationType = HeuristicLab.Analysis.DataTableVisualProperties.DataTableHistogramAggregation;
34using RegressionType = HeuristicLab.Analysis.ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType;
35
36namespace HeuristicLab.DataPreprocessing.Views {
37  [View("Scatter Plot Multi View")]
38  [Content(typeof(MultiScatterPlotContent), true)]
39  public sealed partial class ScatterPlotMultiView : PreprocessingCheckedVariablesView {
40    private readonly IDictionary<string, Label> columnHeaderCache = new Dictionary<string, Label>();
41    private readonly IDictionary<string, VerticalLabel> rowHeaderCache = new Dictionary<string, VerticalLabel>();
42    private readonly IDictionary<Tuple<string/*col*/, string/*row*/>, Control> bodyCache = new Dictionary<Tuple<string, string>, Control>();
43
44    public new MultiScatterPlotContent Content {
45      get { return (MultiScatterPlotContent)base.Content; }
46      set { base.Content = value; }
47    }
48
49    public ScatterPlotMultiView() {
50      InitializeComponent();
51
52      oldWidth = (int)widthNumericUpDown.Value;
53      oldHeight = (int)heightNumericUpDown.Value;
54
55      regressionTypeComboBox.DataSource = Enum.GetValues(typeof(RegressionType));
56      regressionTypeComboBox.SelectedItem = RegressionType.None;
57
58      aggregationComboBox.DataSource = Enum.GetValues(typeof(AggregationType));
59      aggregationComboBox.SelectedItem = AggregationType.Overlapping;
60
61      legendOrderComboBox.DataSource = Enum.GetValues(typeof(PreprocessingChartContent.LegendOrder));
62      legendOrderComboBox.SelectedItem = PreprocessingChartContent.LegendOrder.Alphabetically;
63
64      #region Initialize Scrollbars
65      columnHeaderScrollPanel.HorizontalScroll.Enabled = true;
66      columnHeaderScrollPanel.VerticalScroll.Enabled = false;
67      columnHeaderScrollPanel.HorizontalScroll.Visible = false;
68      columnHeaderScrollPanel.VerticalScroll.Visible = false;
69
70      rowHeaderScrollPanel.HorizontalScroll.Enabled = false;
71      rowHeaderScrollPanel.VerticalScroll.Enabled = true;
72      rowHeaderScrollPanel.HorizontalScroll.Visible = false;
73      rowHeaderScrollPanel.VerticalScroll.Visible = false;
74
75      bodyScrollPanel.HorizontalScroll.Enabled = true;
76      bodyScrollPanel.VerticalScroll.Enabled = true;
77      bodyScrollPanel.HorizontalScroll.Visible = true;
78      bodyScrollPanel.VerticalScroll.Visible = true;
79      bodyScrollPanel.AutoScroll = true;
80      #endregion
81
82      bodyScrollPanel.MouseWheel += bodyScrollPanel_MouseWheel;
83    }
84
85    protected override void OnContentChanged() {
86      base.OnContentChanged();
87      if (Content != null) {
88        groupingComboBox.Items.Add(string.Empty);
89        foreach (string var in PreprocessingChartContent.GetVariableNamesForGrouping(Content.PreprocessingData)) {
90          groupingComboBox.Items.Add(var);
91        }
92        SuppressCheckedChangedUpdate = true;
93        groupingComboBox.SelectedItem = Content.GroupingVariable ?? string.Empty;
94        SuppressCheckedChangedUpdate = false;
95
96        // uncheck variables that max 20 vars are selected initially
97        var variables = Content.VariableItemList;
98        int numChecked = variables.CheckedItems.Count();
99        if (numChecked > 20) {
100          string message = string.Format("Display all {0} input variables ({1} charts)?" + Environment.NewLine +
101                                         "Press No to reduce the number of checked variables to 20." + Environment.NewLine +
102                                         "Press Cancel to uncheck all.",
103            numChecked, numChecked * numChecked);
104          var dialogResult = MessageBox.Show(this, message, "Display All Input Variables?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
105          if (dialogResult == DialogResult.No || dialogResult == DialogResult.Cancel) {
106            SuppressCheckedChangedUpdate = true;
107            IEnumerable<StringValue> toUncheck = variables;
108            if (dialogResult == DialogResult.No) // only show the first 20
109              toUncheck = variables.CheckedItems.Reverse().Take(numChecked - 20).Select(x => x.Value);
110            foreach (var var in toUncheck)
111              Content.VariableItemList.SetItemCheckedState(var, false);
112            SuppressCheckedChangedUpdate = false;
113          }
114        }
115        GenerateCharts(true);
116      }
117    }
118
119    protected override void SetEnabledStateOfControls() {
120      base.SetEnabledStateOfControls();
121      var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
122      polynomialRegressionOrderNumericUpDown.Enabled = regressionType == RegressionType.Polynomial;
123      sizeGroupBox.Enabled = Content != null;
124      pointsGroupBox.Enabled = Content != null;
125      groupingComboBox.Enabled = Content != null;
126      regressionGroupBox.Enabled = Content != null;
127    }
128
129    protected override void CheckedItemsChanged(object sender, CollectionItemsChangedEventArgs<IndexedItem<StringValue>> checkedItems) {
130      base.CheckedItemsChanged(sender, checkedItems);
131      if (SuppressCheckedChangedUpdate) return;
132
133      foreach (var variable in checkedItems.Items) {
134        if (Content.VariableItemList.ItemChecked(variable.Value))
135          ShowChartOnTable(variable.Value.Value, variable.Index);
136        else
137          HideChartFromTable(variable.Value.Value, variable.Index);
138      }
139    }
140
141    #region Show and Hide charts
142    private void ShowChartOnTable(string variable, int idx) {
143      frameTableLayoutPanel.SuspendLayout();
144
145      // show column header
146      var colH = columnHeaderTableLayoutPanel;
147      colH.ColumnStyles[idx].Width = GetColumnWidth();
148      if (colH.GetControlFromPosition(idx, 0) == null)
149        colH.Controls.Add(GetColumnHeader(variable), idx, 0);
150      else
151        colH.GetControlFromPosition(idx, 0).Visible = true;
152
153      // show row header
154      var rowH = rowHeaderTableLayoutPanel;
155      rowH.RowStyles[idx].Height = GetRowHeight();
156      if (rowH.GetControlFromPosition(0, idx) == null)
157        rowH.Controls.Add(GetRowHeader(variable), 0, idx);
158      else
159        rowH.GetControlFromPosition(0, idx).Visible = true;
160
161      // show body
162      var body = bodyTableLayoutPanel;
163      ShowColumnHelper(body, idx, r => GetBody(variable, Content.VariableItemList[r].Value));
164      ShowRowHelper(body, idx, c => GetBody(Content.VariableItemList[c].Value, variable));
165
166      frameTableLayoutPanel.ResumeLayout(true);
167    }
168    private void ShowColumnHelper(TableLayoutPanel tlp, int idx, Func<int, Control> creatorFunc) {
169      tlp.ColumnStyles[idx].Width = GetColumnWidth();
170      for (int r = 0; r < tlp.RowCount; r++) {
171        if (Content.VariableItemList.ItemChecked(Content.VariableItemList[r])) {
172          var control = tlp.GetControlFromPosition(idx, r);
173          if (control == null)
174            tlp.Controls.Add(creatorFunc(r), idx, r);
175          else
176            control.Visible = true;
177        }
178      }
179    }
180    private void ShowRowHelper(TableLayoutPanel tlp, int idx, Func<int, Control> creatorFunc) {
181      tlp.RowStyles[idx].Height = GetRowHeight();
182      for (int c = 0; c < tlp.ColumnCount; c++) {
183        if (Content.VariableItemList.ItemChecked(Content.VariableItemList[c])) {
184          var control = tlp.GetControlFromPosition(c, idx);
185          if (control == null)
186            tlp.Controls.Add(creatorFunc(c), c, idx);
187          else
188            tlp.GetControlFromPosition(c, idx).Visible = true;
189        }
190      }
191    }
192
193    private void HideChartFromTable(string variable, int idx) {
194      frameTableLayoutPanel.SuspendLayout();
195
196      // hide column header
197      var colH = columnHeaderTableLayoutPanel;
198      HideColumnHelper(colH, idx);
199
200      // hide row header
201      var rowH = rowHeaderTableLayoutPanel;
202      HideRowHelper(rowH, idx);
203
204      // hide from body
205      var body = bodyTableLayoutPanel;
206      HideColumnHelper(body, idx);
207      HideRowHelper(body, idx);
208
209      frameTableLayoutPanel.ResumeLayout(true);
210    }
211    private void HideColumnHelper(TableLayoutPanel tlp, int idx) {
212      tlp.ColumnStyles[idx].Width = 0;
213      // hide controls
214      for (int r = 0; r < tlp.RowCount; r++) {
215        var control = tlp.GetControlFromPosition(idx, r);
216        if (control != null)
217          control.Visible = false;
218      }
219    }
220    private void HideRowHelper(TableLayoutPanel tlp, int idx) {
221      tlp.RowStyles[idx].Height = 0;
222      // hide controls
223      for (int c = 0; c < tlp.ColumnCount; c++) {
224        var control = tlp.GetControlFromPosition(c, idx);
225        if (control != null)
226          control.Visible = false;
227      }
228    }
229    #endregion
230
231    #region Add/Remove/Update Variable
232    protected override void AddVariable(string name) {
233      base.AddVariable(name);
234      if (IsVariableChecked(name))
235        AddChartToTable(name);
236    }
237    protected override void RemoveVariable(string name) {
238      base.RemoveVariable(name);
239
240      if (IsVariableChecked(name)) {
241        RemoveChartFromTable(name);
242      }
243
244      // clear caches
245      columnHeaderCache[name].Dispose();
246      columnHeaderCache.Remove(name);
247      rowHeaderCache[name].Dispose();
248      rowHeaderCache.Remove(name);
249      var keys = bodyCache.Keys.Where(t => t.Item1 == name || t.Item2 == name).ToList();
250      foreach (var key in keys) {
251        bodyCache[key].Dispose();
252        bodyCache.Remove(key);
253      }
254    }
255    protected override void UpdateVariable(string name) {
256      base.UpdateVariable(name);
257      RemoveVariable(name);
258      AddVariable(name);
259    }
260    protected override void ResetAllVariables() {
261      GenerateCharts(true);
262    }
263
264    private void AddChartToTable(string variable) {
265      frameTableLayoutPanel.SuspendLayout();
266
267      // find index to insert
268      var variables = Content.VariableItemList.Select(v => v.Value).ToList();
269      int idx = variables              // all variables
270        .TakeWhile(t => t != variable) // ... until the variable that was checked
271        .Count(IsVariableChecked);     // ... how many checked variables
272
273      // add column header
274      var colH = columnHeaderTableLayoutPanel;
275      AddColumnHelper(colH, idx, _ => GetColumnHeader(variable));
276
277      // add row header
278      var rowH = rowHeaderTableLayoutPanel;
279      AddRowHelper(rowH, idx, _ => GetRowHeader(variable));
280
281      // add body
282      var body = bodyTableLayoutPanel;
283      var vars = GetCheckedVariables();
284      var varsMinus = vars.Except(new[] { variable }).ToList();
285      AddColumnHelper(body, idx, r => GetBody(variable, varsMinus[r])); // exclude "variable" because the row for it does not exist yet
286      AddRowHelper(body, idx, c => GetBody(vars[c], variable));
287
288      frameTableLayoutPanel.ResumeLayout(true);
289    }
290    private void AddColumnHelper(TableLayoutPanel tlp, int idx, Func<int, Control> creatorFunc) {
291      // add column
292      tlp.ColumnCount++;
293      tlp.ColumnStyles.Insert(idx, new ColumnStyle(SizeType.Absolute, GetColumnWidth()));
294      // shift right
295      for (int c = tlp.ColumnCount; c > idx - 1; c--) {
296        for (int r = 0; r < tlp.RowCount; r++) {
297          var control = tlp.GetControlFromPosition(c, r);
298          if (control != null) {
299            tlp.SetColumn(control, c + 1);
300          }
301        }
302      }
303      // add controls
304      for (int r = 0; r < tlp.RowCount; r++) {
305        if (tlp.GetControlFromPosition(idx, r) == null)
306          tlp.Controls.Add(creatorFunc(r), idx, r);
307      }
308
309    }
310    private void AddRowHelper(TableLayoutPanel tlp, int idx, Func<int, Control> creatorFunc) {
311      // add row
312      tlp.RowCount++;
313      tlp.RowStyles.Insert(idx, new RowStyle(SizeType.Absolute, GetRowHeight()));
314      // shift right
315      for (int r = tlp.RowCount; r > idx - 1; r--) {
316        for (int c = 0; c < tlp.ColumnCount; c++) {
317          var control = tlp.GetControlFromPosition(c, r);
318          if (control != null) {
319            tlp.SetRow(control, r + 1);
320          }
321        }
322      }
323      // add controls
324      for (int c = 0; c < tlp.ColumnCount; c++)
325        if (tlp.GetControlFromPosition(c, idx) == null)
326          tlp.Controls.Add(creatorFunc(c), c, idx);
327    }
328
329    private void RemoveChartFromTable(string variable) {
330      frameTableLayoutPanel.SuspendLayout();
331
332      // remove column header
333      var colH = columnHeaderTableLayoutPanel;
334      int colIdx = colH.GetColumn(colH.Controls[variable]);
335      RemoveColumnHelper(colH, colIdx);
336
337      // remove row header
338      var rowH = rowHeaderTableLayoutPanel;
339      int rowIdx = rowH.GetRow(rowH.Controls[variable]);
340      RemoveRowHelper(rowH, rowIdx);
341
342      // remove from body
343      var body = bodyTableLayoutPanel;
344      RemoveColumnHelper(body, colIdx);
345      RemoveRowHelper(body, rowIdx);
346
347      frameTableLayoutPanel.ResumeLayout(true);
348    }
349    private void RemoveColumnHelper(TableLayoutPanel tlp, int idx) {
350      // remove controls
351      for (int r = 0; r < tlp.RowCount; r++)
352        tlp.Controls.Remove(tlp.GetControlFromPosition(idx, r));
353      // shift left
354      for (int c = idx + 1; c < tlp.ColumnCount; c++) {
355        for (int r = 0; r < tlp.RowCount; r++) {
356          var control = tlp.GetControlFromPosition(c, r);
357          if (control != null) {
358            tlp.SetColumn(control, c - 1);
359          }
360        }
361      }
362      // delete column
363      tlp.ColumnStyles.RemoveAt(tlp.ColumnCount - 1);
364      tlp.ColumnCount--;
365    }
366    private void RemoveRowHelper(TableLayoutPanel tlp, int idx) {
367      // remove controls
368      for (int c = 0; c < tlp.ColumnCount; c++)
369        tlp.Controls.Remove(tlp.GetControlFromPosition(c, idx));
370      // shift left
371      for (int r = idx + 1; r < tlp.RowCount; r++) {
372        for (int c = 0; c < tlp.ColumnCount; c++) {
373          var control = tlp.GetControlFromPosition(c, r);
374          if (control != null) {
375            tlp.SetRow(control, r - 1);
376          }
377        }
378      }
379      // delete rows
380      tlp.RowStyles.RemoveAt(tlp.RowCount - 1);
381      tlp.RowCount--;
382    }
383    #endregion
384
385    #region Creating Headers and Body
386    private Label GetColumnHeader(string variable) {
387      if (!columnHeaderCache.ContainsKey(variable)) {
388        columnHeaderCache.Add(variable, new Label() {
389          Text = variable,
390          TextAlign = ContentAlignment.MiddleCenter,
391          Name = variable,
392          Height = columnHeaderTableLayoutPanel.Height,
393          Dock = DockStyle.Fill,
394          Margin = new Padding(3)
395        });
396      }
397      return columnHeaderCache[variable];
398    }
399    private Label GetRowHeader(string variable) {
400      if (!rowHeaderCache.ContainsKey(variable)) {
401        rowHeaderCache.Add(variable, new VerticalLabel() {
402          Text = variable,
403          TextAlign = ContentAlignment.MiddleCenter,
404          Name = variable,
405          Width = rowHeaderTableLayoutPanel.Width,
406          Height = columnHeaderScrollPanel.Width,
407          Dock = DockStyle.Fill,
408          Margin = new Padding(3)
409        });
410      }
411      return rowHeaderCache[variable];
412    }
413    private Control GetBody(string colVariable, string rowVariable) {
414      var key = Tuple.Create(colVariable, rowVariable);
415      if (!bodyCache.ContainsKey(key)) {
416        if (rowVariable == colVariable) { // use historgram if x and y variable are equal
417          var dataTable = HistogramContent.CreateHistogram(
418            Content.PreprocessingData,
419            rowVariable,
420            (string)groupingComboBox.SelectedItem,
421            (AggregationType)aggregationComboBox.SelectedItem,
422            (PreprocessingChartContent.LegendOrder)legendOrderComboBox.SelectedItem);
423          dataTable.VisualProperties.Title = string.Empty;
424          foreach (var dataRow in dataTable.Rows) {
425            dataRow.VisualProperties.IsVisibleInLegend = legendCheckbox.Checked && groupingComboBox.SelectedIndex > 0;
426          }
427          var pcv = new DataTableView {
428            Name = key.ToString(),
429            Content = dataTable,
430            Dock = DockStyle.Fill,
431            ShowChartOnly = true
432          };
433          //pcv.ChartDoubleClick += HistogramDoubleClick;  // ToDo: not working; double click is already handled by the chart
434          bodyCache.Add(key, pcv);
435        } else { //scatter plot
436          var scatterPlot = ScatterPlotContent.CreateScatterPlot(Content.PreprocessingData,
437            colVariable,
438            rowVariable,
439            (string)groupingComboBox.SelectedItem,
440            (PreprocessingChartContent.LegendOrder)legendOrderComboBox.SelectedItem);
441          var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
442          int order = (int)polynomialRegressionOrderNumericUpDown.Value;
443          int i = 0;
444          var colors = PreprocessingChartView.Colors;
445          foreach (var row in scatterPlot.Rows) {
446            row.VisualProperties.PointSize = (int)pointSizeNumericUpDown.Value;
447            row.VisualProperties.Color = Color.FromArgb((int)(pointOpacityNumericUpDown.Value * 255),
448              row.VisualProperties.Color.IsEmpty ? colors[i++ % colors.Length] : row.VisualProperties.Color);
449            row.VisualProperties.IsVisibleInLegend = legendCheckbox.Checked && groupingComboBox.SelectedIndex > 0;
450            row.VisualProperties.IsRegressionVisibleInLegend = false;
451            row.VisualProperties.RegressionType = regressionType;
452            row.VisualProperties.PolynomialRegressionOrder = order;
453          }
454          scatterPlot.VisualProperties.Title = string.Empty;
455          var scatterPlotView = new ScatterPlotView {
456            Name = key.ToString(),
457            Content = scatterPlot,
458            Dock = DockStyle.Fill,
459            ShowChartOnly = true
460            //ShowLegend = false,
461            //XAxisFormat = "G3"
462          };
463          //scatterPlotView.DoubleClick += ScatterPlotDoubleClick; // ToDo: not working; double click is already handled by the chart
464          bodyCache.Add(key, scatterPlotView);
465        }
466      }
467      return bodyCache[key];
468    }
469    #endregion
470
471    protected override void CheckedChangedUpdate() {
472      GenerateCharts(false); // only checked-changes -> reuse cached values
473    }
474
475    #region Generate Charts
476    private void GenerateCharts(bool clearCache) {
477      if (Content == null || SuppressCheckedChangedUpdate) return;
478
479      // Clear old layouts and cache
480      foreach (var tableLayoutPanel in new[] { columnHeaderTableLayoutPanel, rowHeaderTableLayoutPanel, bodyTableLayoutPanel }) {
481        tableLayoutPanel.Controls.Clear();
482        tableLayoutPanel.ColumnStyles.Clear();
483        tableLayoutPanel.RowStyles.Clear();
484      }
485
486      if (clearCache) {
487        foreach (var control in bodyCache.Values.Concat(columnHeaderCache.Values).Concat(rowHeaderCache.Values)) {
488          control.Dispose();
489        }
490        columnHeaderCache.Clear();
491        rowHeaderCache.Clear();
492        bodyCache.Clear();
493      }
494
495      var variables = Content.VariableItemList.Select(x => x.Value).ToList();
496
497      // Set row and column count
498      columnHeaderTableLayoutPanel.ColumnCount = variables.Count;
499      rowHeaderTableLayoutPanel.RowCount = variables.Count;
500      bodyTableLayoutPanel.ColumnCount = variables.Count;
501      bodyTableLayoutPanel.RowCount = variables.Count;
502
503      // Set column and row layout
504      for (int i = 0; i < variables.Count; i++) {
505        bool @checked = Content.VariableItemList.ItemChecked(Content.VariableItemList[i]);
506        columnHeaderTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, @checked ? GetColumnWidth() : 0));
507        rowHeaderTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, @checked ? GetRowHeight() : 0));
508        bodyTableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, @checked ? GetColumnWidth() : 0));
509        bodyTableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, @checked ? GetRowHeight() : 0));
510      }
511
512      frameTableLayoutPanel.SuspendLayout();
513      AddHeaderToTableLayoutPanels();
514      AddChartsToTableLayoutPanel();
515      UpdateHeaderMargin();
516      frameTableLayoutPanel.ResumeLayout(true);
517    }
518
519    private void AddHeaderToTableLayoutPanels() {
520      for (int i = 0; i < Content.VariableItemList.Count; i++) {
521        var variable = Content.VariableItemList[i];
522        if (Content.VariableItemList.ItemChecked(variable)) {
523          columnHeaderTableLayoutPanel.Controls.Add(GetColumnHeader(variable.Value), i, 0);
524          rowHeaderTableLayoutPanel.Controls.Add(GetRowHeader(variable.Value), 0, i);
525        }
526      }
527    }
528    private void AddChartsToTableLayoutPanel() {
529      for (int c = 0; c < Content.VariableItemList.Count; c++) {
530        var colVar = Content.VariableItemList[c].Value;
531        if (!IsVariableChecked(colVar)) continue;
532        for (int r = 0; r < Content.VariableItemList.Count; r++) {
533          var rowVar = Content.VariableItemList[r].Value;
534          if (!IsVariableChecked(rowVar)) continue;
535          bodyTableLayoutPanel.Controls.Add(GetBody(colVar, rowVar), c, r);
536        }
537      }
538      UpdateRegressionLine();
539    }
540
541    #endregion
542
543    #region DoubleClick Events
544    //Open scatter plot in new tab with new content when double clicked
545    private void ScatterPlotDoubleClick(object sender, EventArgs e) {
546      var scatterPlotView = (ScatterPlotView)sender;
547      var scatterContent = new SingleScatterPlotContent(Content.PreprocessingData);
548      ScatterPlot scatterPlot = scatterPlotView.Content;
549
550      //Extract variable names from scatter plot and set them in content
551      if (scatterPlot.Rows.Count == 1) {
552        string[] variables = scatterPlot.Rows.ElementAt(0).Name.Split(new string[] { " - " }, StringSplitOptions.None); // extract variable names from string
553        scatterContent.SelectedXVariable = variables[0];
554        scatterContent.SelectedYVariable = variables[1];
555      }
556
557      MainFormManager.MainForm.ShowContent(scatterContent, typeof(ScatterPlotSingleView)); // open in new tab
558    }
559
560    //open histogram in new tab with new content when double clicked
561    private void HistogramDoubleClick(object sender, EventArgs e) {
562      DataTableView pcv = (DataTableView)sender;
563      HistogramContent histoContent = new HistogramContent(Content.PreprocessingData);  // create new content     
564                                                                                        //ToDo: histoContent.VariableItemList = Content.CreateVariableItemList();
565      var dataTable = pcv.Content;
566
567      //Set variable item list from with variable from data table
568      if (dataTable.Rows.Count == 1) { // only one data row should be in data table
569        string variableName = dataTable.Rows.ElementAt(0).Name;
570
571        // set only variable name checked
572        foreach (var checkedItem in histoContent.VariableItemList) {
573          histoContent.VariableItemList.SetItemCheckedState(checkedItem, checkedItem.Value == variableName);
574        }
575      }
576      MainFormManager.MainForm.ShowContent(histoContent, typeof(HistogramView)); // open in new tab
577    }
578    #endregion
579
580    #region Scrolling
581    private void bodyScrollPanel_Scroll(object sender, ScrollEventArgs e) {
582      SyncScroll();
583
584      UpdateHeaderMargin();
585    }
586    private void bodyScrollPanel_MouseWheel(object sender, MouseEventArgs e) {
587      // Scrolling with the mouse wheel is not captured in the Scoll event
588      SyncScroll();
589    }
590    private void SyncScroll() {
591      frameTableLayoutPanel.SuspendRepaint();
592
593      columnHeaderScrollPanel.HorizontalScroll.Minimum = bodyScrollPanel.HorizontalScroll.Minimum;
594      columnHeaderScrollPanel.HorizontalScroll.Maximum = bodyScrollPanel.HorizontalScroll.Maximum;
595      rowHeaderScrollPanel.VerticalScroll.Minimum = bodyScrollPanel.VerticalScroll.Minimum;
596      rowHeaderScrollPanel.VerticalScroll.Maximum = bodyScrollPanel.VerticalScroll.Maximum;
597
598      columnHeaderScrollPanel.HorizontalScroll.Value = Math.Max(bodyScrollPanel.HorizontalScroll.Value, 1);
599      rowHeaderScrollPanel.VerticalScroll.Value = Math.Max(bodyScrollPanel.VerticalScroll.Value, 1);
600      // minimum 1 is nececary  because of two factors:
601      // - setting the Value-property of Horizontal/VerticalScroll updates the internal state but the Value-property stays 0
602      // - setting the same number of the Value-property has no effect
603      // since the Value-property is always 0, setting it to 0 would have no effect; so it is set to 1 instead
604
605      frameTableLayoutPanel.ResumeRepaint(true);
606    }
607    // add a margin to the header table layouts if the scollbar is visible to account for the width/height of the scrollbar
608    private void UpdateHeaderMargin() {
609      columnHeaderScrollPanel.Margin = new Padding(0, 0, bodyScrollPanel.VerticalScroll.Visible ? SystemInformation.VerticalScrollBarWidth : 0, 0);
610      rowHeaderScrollPanel.Margin = new Padding(0, 0, 0, bodyScrollPanel.HorizontalScroll.Visible ? SystemInformation.HorizontalScrollBarHeight : 0);
611    }
612    #endregion
613
614    #region Sizing of Charts
615    private int oldWidth;
616    private int oldHeight;
617    private float AspectRatio {
618      get {
619        if (oldWidth == 0 || oldHeight == 0) return 1;
620        return (float)oldWidth / oldHeight;
621      }
622    }
623    private bool lockChange = false;
624
625    private int GetColumnWidth() { return (int)widthNumericUpDown.Value; }
626    private int GetRowHeight() { return (int)heightNumericUpDown.Value; }
627
628    private void widthNumericUpDown_ValueChanged(object sender, EventArgs e) {
629      frameTableLayoutPanel.SuspendRepaint();
630      if (lockAspectCheckBox.Checked && !lockChange) {
631        lockChange = true;
632        heightNumericUpDown.Value = (int)((double)widthNumericUpDown.Value / AspectRatio);
633        lockChange = false;
634      }
635      for (int i = 0; i < columnHeaderTableLayoutPanel.ColumnCount; i++) {
636        if (Content.VariableItemList.ItemChecked(Content.VariableItemList[i])) {
637          columnHeaderTableLayoutPanel.ColumnStyles[i].Width = GetColumnWidth();
638          bodyTableLayoutPanel.ColumnStyles[i].Width = GetColumnWidth();
639        }
640      }
641      oldWidth = GetColumnWidth();
642      oldHeight = GetRowHeight();
643      frameTableLayoutPanel.ResumeRepaint(true);
644    }
645    private void heightNumericUpDown_ValueChanged(object sender, EventArgs e) {
646      frameTableLayoutPanel.SuspendRepaint();
647      if (lockAspectCheckBox.Checked && !lockChange) {
648        lockChange = true;
649        widthNumericUpDown.Value = (int)((double)heightNumericUpDown.Value * AspectRatio);
650        lockChange = false;
651      }
652      for (int i = 0; i < rowHeaderTableLayoutPanel.RowCount; i++) {
653        if (Content.VariableItemList.ItemChecked(Content.VariableItemList[i])) {
654          rowHeaderTableLayoutPanel.RowStyles[i].Height = GetRowHeight();
655          bodyTableLayoutPanel.RowStyles[i].Height = GetRowHeight();
656        }
657      }
658      oldWidth = GetColumnWidth();
659      oldHeight = GetRowHeight();
660      frameTableLayoutPanel.ResumeRepaint(true);
661    }
662    private void pointSizeNumericUpDown_ValueChanged(object sender, EventArgs e) {
663      int pointSize = (int)pointSizeNumericUpDown.Value;
664      foreach (var control in bodyCache.ToList()) {
665        var scatterPlotView = control.Value as ScatterPlotView;
666        if (scatterPlotView != null) {
667          foreach (var row in scatterPlotView.Content.Rows) {
668            row.VisualProperties.PointSize = pointSize;
669          }
670        }
671      }
672    }
673    private void pointOpacityNumericUpDown_ValueChanged(object sender, EventArgs e) {
674      float opacity = (float)pointOpacityNumericUpDown.Value;
675      foreach (var control in bodyCache.ToList()) {
676        var scatterPlotView = control.Value as ScatterPlotView;
677        if (scatterPlotView != null) {
678          foreach (var row in scatterPlotView.Content.Rows) {
679            var color = row.VisualProperties.Color;
680            if (color.IsEmpty)
681              color = PreprocessingChartView.Colors.First();
682            row.VisualProperties.Color = Color.FromArgb((int)(opacity * 255), color);
683          }
684        }
685      }
686    }
687    #endregion
688
689    #region Regression Line
690    private void regressionTypeComboBox_SelectedValueChanged(object sender, EventArgs e) {
691      var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
692      polynomialRegressionOrderNumericUpDown.Enabled = regressionType == RegressionType.Polynomial;
693      UpdateRegressionLine();
694    }
695
696    private void polynomialRegressionOrderNumericUpDown_ValueChanged(object sender, EventArgs e) {
697      UpdateRegressionLine();
698    }
699
700    private void UpdateRegressionLine() {
701      var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
702      int order = (int)polynomialRegressionOrderNumericUpDown.Value;
703
704      foreach (var control in bodyCache.ToList()) {
705        // hidden chart => reset cache
706        if (!bodyTableLayoutPanel.Controls.Contains(control.Value)) {
707          bodyCache.Remove(control.Key);
708        }
709
710        var scatterPlotView = control.Value as ScatterPlotView;
711        if (scatterPlotView != null) {
712          foreach (var row in scatterPlotView.Content.Rows) {
713            row.VisualProperties.IsRegressionVisibleInLegend = false;
714            row.VisualProperties.RegressionType = regressionType;
715            row.VisualProperties.PolynomialRegressionOrder = order;
716          }
717        }
718      }
719    }
720    #endregion
721
722    #region Grouping
723    private void groupingComboBox_SelectedIndexChanged(object sender, EventArgs e) {
724      aggregationLabel.Enabled = groupingComboBox.SelectedIndex > 0;
725      aggregationComboBox.Enabled = groupingComboBox.SelectedIndex > 0;
726      legendGroupBox.Enabled = groupingComboBox.SelectedIndex > 0;
727      GenerateCharts(true); // new series within charts -> clear cache
728    }
729
730    private void aggregationComboBox_SelectedIndexChanged(object sender, EventArgs e) {
731      var aggregation = (AggregationType)aggregationComboBox.SelectedValue;
732      foreach (var control in bodyCache.ToList()) {
733        // hidden chart => reset cache
734        if (!bodyTableLayoutPanel.Controls.Contains(control.Value)) {
735          bodyCache.Remove(control.Key);
736        }
737
738        var histogramView = control.Value as DataTableView;
739        if (histogramView != null) {
740          histogramView.Content.VisualProperties.HistogramAggregation = aggregation;
741        }
742      }
743    }
744
745    private void legendCheckbox_CheckedChanged(object sender, EventArgs e) {
746      foreach (var control in bodyCache.ToList()) {
747        var histogramControl = control.Value as DataTableView;
748        if (histogramControl != null) {
749          foreach (var row in histogramControl.Content.Rows) {
750            row.VisualProperties.IsVisibleInLegend = legendCheckbox.Checked && groupingComboBox.SelectedIndex > 0;
751          }
752        }
753        var scatterplotControl = control.Value as ScatterPlotView;
754        if (scatterplotControl != null) {
755          foreach (var row in scatterplotControl.Content.Rows) {
756            row.VisualProperties.IsVisibleInLegend = legendCheckbox.Checked && groupingComboBox.SelectedIndex > 0;
757          }
758        }
759      }
760    }
761
762    private void legendOrderComboBox_SelectedIndexChanged(object sender, EventArgs e) {
763      GenerateCharts(true);
764    }
765    #endregion
766  }
767}
768
Note: See TracBrowser for help on using the repository browser.