source: branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotMultiView.cs @ 15021

Last change on this file since 15021 was 15021, checked in by pfleck, 5 years ago

#2709

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