Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/PreprocessingChartView.cs @ 14343

Last change on this file since 14343 was 14270, checked in by pfleck, 8 years ago

#2663

  • Fixed reordering issue by enabling/disabling series rather than removing the DataRow.
  • Reduced flickering by suspending layouting during variable un/rechecking.
File size: 14.0 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.Linq;
25using System.Windows.Forms;
26using HeuristicLab.Analysis;
27using HeuristicLab.Collections;
28using HeuristicLab.Core.Views;
29using HeuristicLab.Data;
30using HeuristicLab.MainForm;
31
32namespace HeuristicLab.DataPreprocessing.Views {
33  [View("Preprocessing Chart View")]
34  [Content(typeof(PreprocessingChartContent), false)]
35  public partial class PreprocessingChartView : ItemView {
36
37    private PreprocessingDataTable dataTable;
38    private List<PreprocessingDataTable> dataTablePerVariable;
39    private List<DataRow> dataRows;
40    private List<DataRow> selectedDataRows;
41
42    protected DataRowVisualProperties.DataRowChartType chartType;
43    protected string chartTitle;
44
45    private const string DEFAULT_CHART_TITLE = "Chart";
46    private const int FIXED_CHART_SIZE = 300;
47    private const int MAX_TABLE_AUTO_SIZE_ROWS = 3;
48
49    public IEnumerable<double> Classification { get; set; }
50    public bool IsDetailedChartViewEnabled { get; set; }
51
52    public PreprocessingChartView() {
53      InitializeComponent();
54      chartType = DataRowVisualProperties.DataRowChartType.Line;
55      chartTitle = DEFAULT_CHART_TITLE;
56    }
57
58    //Variable selection changed
59    //Add or remove data row
60    private void CheckedItemsChanged(object sender, CollectionItemsChangedEventArgs<IndexedItem<StringValue>> checkedItems) {
61      tableLayoutPanel.SuspendLayout();
62      foreach (IndexedItem<StringValue> item in checkedItems.Items) {
63        string variableName = item.Value.Value;
64
65        // not checked -> remove
66        if (!VariableIsChecked(variableName)) {
67          dataTableView.SetRowEnabled(variableName, false);
68          dataTable.SelectedRows.Remove(variableName);
69          dataTablePerVariable.Remove(dataTablePerVariable.Find(x => (x.Name == variableName)));
70        } else {
71          DataRow row = GetDataRow(variableName);
72          DataRow selectedRow = GetSelectedDataRow(variableName);
73          dataTableView.SetRowEnabled(variableName, true);
74
75          PreprocessingDataTable pdt = new PreprocessingDataTable(variableName);
76          pdt.Rows.Add(row);
77          // dataTablePerVariable does not contain unchecked variables => reduce insert position by number of uncheckt variables to correct the index
78          int uncheckedUntilVariable = checkedItemList.Content.TakeWhile(x => x.Value != variableName).Count(x => !checkedItemList.Content.ItemChecked(x));
79          dataTablePerVariable.Insert(item.Index - uncheckedUntilVariable, pdt);
80
81          //update selection
82          if (selectedRow != null) {
83            dataTable.SelectedRows.Add(selectedRow);
84            pdt.SelectedRows.Add(selectedRow);
85          }
86        }
87      }
88
89      // update chart if not in all in one mode
90      if (Content != null && !Content.AllInOneMode)
91        GenerateChart();
92      tableLayoutPanel.ResumeLayout(true);
93    }
94
95    private bool VariableIsChecked(string name) {
96      return Content.VariableItemList.CheckedItems.Any(x => x.Value.Value == name);
97    }
98
99    protected override void RegisterContentEvents() {
100      base.RegisterContentEvents();
101      Content.PreprocessingData.Changed += PreprocessingData_Changed;
102      Content.PreprocessingData.SelectionChanged += PreprocessingData_SelctionChanged;
103
104    }
105
106    protected override void DeregisterContentEvents() {
107      base.DeregisterContentEvents();
108      Content.PreprocessingData.Changed -= PreprocessingData_Changed;
109      Content.PreprocessingData.SelectionChanged -= PreprocessingData_SelctionChanged;
110    }
111
112    public new PreprocessingChartContent Content {
113      get { return (PreprocessingChartContent)base.Content; }
114      set { base.Content = value; }
115    }
116
117    private void InitData() {
118      if (Content.VariableItemList == null) {
119        Content.VariableItemList = Content.CreateVariableItemList();
120      } else {
121        var checkedNames = Content.VariableItemList.CheckedItems.Select(x => x.Value.Value);
122        Content.VariableItemList = Content.CreateVariableItemList(checkedNames);
123      }
124      checkedItemList.Content = Content.VariableItemList;
125
126      //Create data tables and data rows
127      dataRows = Content.CreateAllDataRows(chartType);
128      dataTable = new PreprocessingDataTable(chartTitle);
129      dataTablePerVariable = new List<PreprocessingDataTable>();
130
131      //add data rows to data tables according to checked item list
132      foreach (var checkedItem in Content.VariableItemList.CheckedItems) {
133        string variableName = Content.VariableItemList[checkedItem.Index].Value;
134        PreprocessingDataTable d = new PreprocessingDataTable(variableName);
135        DataRow row = GetDataRow(variableName);
136
137        if (row != null) {
138          //add row to data table
139          dataTable.Rows.Add(row);
140
141          //add row to data table per variable
142          d.Rows.Add(row);
143          dataTablePerVariable.Add(d);
144        }
145      }
146
147      UpdateSelection();
148    }
149
150    private void UpdateSelection() {
151
152      //update data table selection
153      selectedDataRows = Content.CreateAllSelectedDataRows(chartType);
154      dataTable.SelectedRows.Clear();
155      foreach (var selectedRow in selectedDataRows) {
156        if (VariableIsChecked(selectedRow.Name))
157          dataTable.SelectedRows.Add(selectedRow);
158      }
159
160      //update data table per variable selection
161      foreach (PreprocessingDataTable d in dataTablePerVariable) {
162        d.SelectedRows.Clear();
163        DataRow row = selectedDataRows.Find(x => x.Name == d.Name);
164        if (row != null)
165          d.SelectedRows.Add(row);
166      }
167
168    }
169
170    private DataRow GetSelectedDataRow(string variableName) {
171      foreach (DataRow row in selectedDataRows) {
172        if (row.Name == variableName)
173          return row;
174      }
175      return null;
176    }
177
178    private DataRow GetDataRow(string variableName) {
179      foreach (DataRow row in dataRows) {
180        if (row.Name == variableName)
181          return row;
182      }
183      return null;
184    }
185
186    protected override void OnContentChanged() {
187      base.OnContentChanged();
188      if (Content != null) {
189        InitData();
190        Content.VariableItemList.CheckedItemsChanged += CheckedItemsChanged;
191        GenerateChart();
192      }
193    }
194
195    // TODO : handle also other changed events
196    void PreprocessingData_Changed(object sender, DataPreprocessingChangedEventArgs e) {
197      switch (e.Type) {
198        case DataPreprocessingChangedEventType.DeleteColumn:
199          RemoveVariable(Content.PreprocessingData.GetVariableName(e.Column));
200          break;
201        case DataPreprocessingChangedEventType.AddColumn:
202          AddVariable(Content.PreprocessingData.GetVariableName(e.Column));
203          break;
204        case DataPreprocessingChangedEventType.ChangeColumn:
205        case DataPreprocessingChangedEventType.ChangeItem:
206          UpdateDataForVariable(Content.PreprocessingData.GetVariableName(e.Column));
207          break;
208        case DataPreprocessingChangedEventType.DeleteRow:
209        case DataPreprocessingChangedEventType.AddRow:
210        case DataPreprocessingChangedEventType.Any:
211        default:
212          //TODO: test with transform
213          InitData();
214          GenerateChart();
215          break;
216      }
217    }
218
219    private void PreprocessingData_SelctionChanged(object sender, EventArgs e) {
220      UpdateSelection();
221    }
222
223    private void UpdateDataForVariable(string variableName) {
224      DataRow newRow = Content.CreateDataRow(variableName, chartType);
225      dataTable.Rows.Remove(variableName);
226      dataTable.Rows.Add(newRow);
227      DataTable dt = dataTablePerVariable.Find(x => x.Rows.Find(y => y.Name == variableName) != null);
228      if (dt != null) {
229        dt.Rows.Remove(variableName);
230        dt.Rows.Add(newRow);
231      }
232    }
233
234    // add variable to data table and item list
235    private void AddVariable(string name) {
236      DataRow row = Content.CreateDataRow(name, chartType);
237      dataTable.Rows.Add(row);
238      PreprocessingDataTable d = new PreprocessingDataTable(name);
239      d.Rows.Add(row);
240      dataTablePerVariable.Add(d);
241      Content.VariableItemList.Add(new StringValue(name));
242      if (!Content.AllInOneMode)
243        GenerateChart();
244    }
245
246    // remove variable from data table and item list
247    private void RemoveVariable(string name) {
248      dataTable.Rows.Remove(name);
249      dataTablePerVariable.Remove(dataTablePerVariable.Find(x => (x.Name == name)));
250
251      StringValue stringValue = FindVariableItemList(name);
252      if (stringValue != null)
253        Content.VariableItemList.Remove(stringValue);
254      if (!Content.AllInOneMode)
255        GenerateChart();
256    }
257
258    private StringValue FindVariableItemList(string name) {
259      foreach (StringValue stringValue in Content.VariableItemList) {
260        if (stringValue.Value == name)
261          return stringValue;
262      }
263      return null;
264    }
265
266    protected void GenerateChart() {
267      ClearTableLayout();
268      if (Content.AllInOneMode) {
269        GenerateSingleChartLayout();
270      } else
271        GenerateMultiChartLayout();
272    }
273
274    private void ClearTableLayout() {
275      //Clear out the existing controls
276      tableLayoutPanel.Controls.Clear();
277
278      //Clear out the existing row and column styles
279      tableLayoutPanel.ColumnStyles.Clear();
280      tableLayoutPanel.RowStyles.Clear();
281      tableLayoutPanel.AutoScroll = false;
282      tableLayoutPanel.AutoScroll = true;
283    }
284
285    private void GenerateSingleChartLayout() {
286      tableLayoutPanel.ColumnCount = 1;
287      tableLayoutPanel.RowCount = 1;
288      tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
289      tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
290      tableLayoutPanel.Controls.Add(dataTableView, 0, 0);
291      dataTableView.Content = dataTable;
292    }
293
294    private int GetNrOfMultiChartColumns(int itemCount) {
295      int columns = 0;
296      if (itemCount <= 2)
297        columns = 1;
298      else if (itemCount <= 6)
299        columns = 2;
300      else
301        columns = 3;
302      return columns;
303    }
304
305    private int GetNrOfMultiChartRows(int itemCount, int columns) {
306      int rows = 0;
307      if (columns == 3)
308        rows = (itemCount + 2) / columns;
309      else if (columns == 2)
310        rows = (itemCount + 1) / columns;
311      else
312        rows = itemCount / columns;
313      return rows;
314    }
315
316
317    private void GenerateMultiChartLayout() {
318      int checkedItemsCnt = 0;
319      foreach (var item in Content.VariableItemList.CheckedItems)
320        checkedItemsCnt++;
321
322      // set columns and rows based on number of items
323      int columns = GetNrOfMultiChartColumns(checkedItemsCnt);
324      int rows = GetNrOfMultiChartRows(checkedItemsCnt, columns);
325
326      tableLayoutPanel.ColumnCount = columns;
327      tableLayoutPanel.RowCount = rows;
328
329      List<PreprocessingDataTable>.Enumerator enumerator = dataTablePerVariable.GetEnumerator();
330      for (int x = 0; x < columns; x++) {
331
332        if (rows <= MAX_TABLE_AUTO_SIZE_ROWS)
333          tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100 / columns));
334        else
335          //scrollbar is shown if there are more than 3 rows -> remove scroll bar width from total width
336          tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, (tableLayoutPanel.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth) / columns));
337        for (int y = 0; y < rows; y++) {
338          //Add a row only when creating the first column
339          if (x == 0) {
340            // fixed chart size when there are more than 3 tables
341            if (rows > MAX_TABLE_AUTO_SIZE_ROWS)
342              tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, FIXED_CHART_SIZE));
343            else
344              tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100 / rows));
345          }
346
347          enumerator.MoveNext();
348          PreprocessingDataTable d = enumerator.Current;
349          AddDataTableToTableLayout(d, x, y);
350
351        }
352      }
353    }
354
355    private void AddDataTableToTableLayout(PreprocessingDataTable dataTable, int x, int y) {
356      PreprocessingDataTableView dataView = new PreprocessingDataTableView();
357      dataView.Classification = Classification;
358      dataView.IsDetailedChartViewEnabled = IsDetailedChartViewEnabled;
359
360      if (dataTable == null) {
361        // dummy panel for empty field
362        Panel p = new Panel();
363        p.Dock = DockStyle.Fill;
364        tableLayoutPanel.Controls.Add(p, y, x);
365      } else {
366        dataView.Content = dataTable;
367        dataView.Dock = DockStyle.Fill;
368        tableLayoutPanel.Controls.Add(dataView, y, x);
369      }
370    }
371
372    //Remove horizontal scroll bar if visible
373    private void tableLayoutPanel_Layout(object sender, LayoutEventArgs e) {
374      if (tableLayoutPanel.HorizontalScroll.Visible) {
375        // Add padding on the right in order to accomodate the vertical scrollbar
376        int vWidth = SystemInformation.VerticalScrollBarWidth;
377        tableLayoutPanel.Padding = new Padding(0, 0, vWidth, 0);
378      } else {
379        // Reset padding
380        tableLayoutPanel.Padding = new Padding(0);
381      }
382    }
383
384  }
385}
386
387
Note: See TracBrowser for help on using the repository browser.