source: branches/DataPreprocessing/HeuristicLab.DataPreprocessing.Views/3.4/PreprocessingChartView.cs @ 10972

Last change on this file since 10972 was 10972, checked in by aesterer, 8 years ago

Chart view refactoring

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