#region License Information
/* HeuristicLab
* Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using HeuristicLab.Analysis;
using HeuristicLab.Collections;
using HeuristicLab.Core.Views;
using HeuristicLab.Data;
using HeuristicLab.MainForm;
namespace HeuristicLab.DataPreprocessing.Views {
[View("Preprocessing Chart View")]
[Content(typeof(PreprocessingChartContent), false)]
public partial class PreprocessingChartView : ItemView {
private PreprocessingDataTable dataTable;
private List dataTablePerVariable;
private List dataRows;
private List selectedDataRows;
protected DataRowVisualProperties.DataRowChartType chartType;
protected string chartTitle;
private const string DEFAULT_CHART_TITLE = "Chart";
private const int FIXED_CHART_SIZE = 300;
private const int MAX_TABLE_AUTO_SIZE_ROWS = 3;
public IEnumerable Classification { get; set; }
public bool IsDetailedChartViewEnabled { get; set; }
public PreprocessingChartView() {
InitializeComponent();
chartType = DataRowVisualProperties.DataRowChartType.Line;
chartTitle = DEFAULT_CHART_TITLE;
}
//Variable selection changed
//Add or remove data row
private void CheckedItemsChanged(object sender, CollectionItemsChangedEventArgs> checkedItems) {
foreach (IndexedItem item in checkedItems.Items) {
string variableName = item.Value.Value;
//variable is displayed -> remove
if (VariableIsDisplayed(variableName)) {
dataTable.Rows.Remove(variableName);
dataTable.SelectedRows.Remove(variableName);
dataTablePerVariable.Remove(dataTablePerVariable.Find(x => (x.Name == variableName)));
//variable isnt't displayed -> add
} else {
DataRow row = GetDataRow(variableName);
DataRow selectedRow = GetSelectedDataRow(variableName);
dataTable.Rows.Add(row);
PreprocessingDataTable pdt = new PreprocessingDataTable(variableName);
pdt.Rows.Add(row);
dataTablePerVariable.Add(pdt);
//update selection
if (selectedRow != null) {
dataTable.SelectedRows.Add(selectedRow);
pdt.SelectedRows.Add(selectedRow);
}
}
}
// update chart if not in all in one mode
if (Content != null && !Content.AllInOneMode)
GenerateChart();
}
private bool VariableIsDisplayed(string name) {
foreach (var item in dataTable.Rows) {
if (item.Name == name)
return true;
}
return false;
}
protected override void RegisterContentEvents() {
base.RegisterContentEvents();
Content.PreprocessingData.Changed += PreprocessingData_Changed;
Content.PreprocessingData.SelectionChanged += PreprocessingData_SelctionChanged;
}
protected override void DeregisterContentEvents() {
base.DeregisterContentEvents();
Content.PreprocessingData.Changed -= PreprocessingData_Changed;
Content.PreprocessingData.SelectionChanged -= PreprocessingData_SelctionChanged;
}
public new PreprocessingChartContent Content {
get { return (PreprocessingChartContent)base.Content; }
set { base.Content = value; }
}
private void InitData() {
if (Content.VariableItemList == null) {
Content.VariableItemList = Content.CreateVariableItemList();
} else {
var checkedNames = Content.VariableItemList.CheckedItems.Select(x => x.Value.Value);
Content.VariableItemList = Content.CreateVariableItemList(checkedNames);
}
checkedItemList.Content = Content.VariableItemList;
//Create data tables and data rows
dataRows = Content.CreateAllDataRows(chartType);
dataTable = new PreprocessingDataTable(chartTitle);
dataTablePerVariable = new List();
//add data rows to data tables according to checked item list
foreach (var checkedItem in Content.VariableItemList.CheckedItems) {
string variableName = Content.VariableItemList[checkedItem.Index].Value;
PreprocessingDataTable d = new PreprocessingDataTable(variableName);
DataRow row = GetDataRow(variableName);
if (row != null) {
//add row to data table
dataTable.Rows.Add(row);
//add row to data table per variable
d.Rows.Add(row);
dataTablePerVariable.Add(d);
}
}
UpdateSelection();
}
private void UpdateSelection() {
//update data table selection
selectedDataRows = Content.CreateAllSelectedDataRows(chartType);
dataTable.SelectedRows.Clear();
foreach (var selectedRow in selectedDataRows) {
if (VariableIsDisplayed(selectedRow.Name))
dataTable.SelectedRows.Add(selectedRow);
}
//update data table per variable selection
foreach (PreprocessingDataTable d in dataTablePerVariable) {
d.SelectedRows.Clear();
DataRow row = selectedDataRows.Find(x => x.Name == d.Name);
if (row != null)
d.SelectedRows.Add(row);
}
}
private DataRow GetSelectedDataRow(string variableName) {
foreach (DataRow row in selectedDataRows) {
if (row.Name == variableName)
return row;
}
return null;
}
private DataRow GetDataRow(string variableName) {
foreach (DataRow row in dataRows) {
if (row.Name == variableName)
return row;
}
return null;
}
protected override void OnContentChanged() {
base.OnContentChanged();
if (Content != null) {
InitData();
Content.VariableItemList.CheckedItemsChanged += CheckedItemsChanged;
GenerateChart();
}
}
// TODO : handle also other changed events
void PreprocessingData_Changed(object sender, DataPreprocessingChangedEventArgs e) {
switch (e.Type) {
case DataPreprocessingChangedEventType.DeleteColumn:
RemoveVariable(Content.PreprocessingData.GetVariableName(e.Column));
break;
case DataPreprocessingChangedEventType.AddColumn:
AddVariable(Content.PreprocessingData.GetVariableName(e.Column));
break;
case DataPreprocessingChangedEventType.ChangeColumn:
case DataPreprocessingChangedEventType.ChangeItem:
UpdateDataForVariable(Content.PreprocessingData.GetVariableName(e.Column));
break;
case DataPreprocessingChangedEventType.DeleteRow:
case DataPreprocessingChangedEventType.AddRow:
case DataPreprocessingChangedEventType.Any:
default:
//TODO: test with transform
InitData();
GenerateChart();
break;
}
}
private void PreprocessingData_SelctionChanged(object sender, EventArgs e) {
UpdateSelection();
}
private void UpdateDataForVariable(string variableName) {
DataRow newRow = Content.CreateDataRow(variableName, chartType);
dataTable.Rows.Remove(variableName);
dataTable.Rows.Add(newRow);
DataTable dt = dataTablePerVariable.Find(x => x.Rows.Find(y => y.Name == variableName) != null);
if (dt != null) {
dt.Rows.Remove(variableName);
dt.Rows.Add(newRow);
}
}
// add variable to data table and item list
private void AddVariable(string name) {
DataRow row = Content.CreateDataRow(name, chartType);
dataTable.Rows.Add(row);
PreprocessingDataTable d = new PreprocessingDataTable(name);
d.Rows.Add(row);
dataTablePerVariable.Add(d);
Content.VariableItemList.Add(new StringValue(name));
if (!Content.AllInOneMode)
GenerateChart();
}
// remove variable from data table and item list
private void RemoveVariable(string name) {
dataTable.Rows.Remove(name);
dataTablePerVariable.Remove(dataTablePerVariable.Find(x => (x.Name == name)));
StringValue stringValue = FindVariableItemList(name);
if (stringValue != null)
Content.VariableItemList.Remove(stringValue);
if (!Content.AllInOneMode)
GenerateChart();
}
private StringValue FindVariableItemList(string name) {
foreach (StringValue stringValue in Content.VariableItemList) {
if (stringValue.Value == name)
return stringValue;
}
return null;
}
protected void GenerateChart() {
ClearTableLayout();
if (Content.AllInOneMode) {
GenerateSingleChartLayout();
} else
GenerateMultiChartLayout();
}
private void ClearTableLayout() {
//Clear out the existing controls
tableLayoutPanel.Controls.Clear();
//Clear out the existing row and column styles
tableLayoutPanel.ColumnStyles.Clear();
tableLayoutPanel.RowStyles.Clear();
tableLayoutPanel.AutoScroll = false;
tableLayoutPanel.AutoScroll = true;
}
private void GenerateSingleChartLayout() {
tableLayoutPanel.ColumnCount = 1;
tableLayoutPanel.RowCount = 1;
tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
tableLayoutPanel.Controls.Add(dataTableView, 0, 0);
dataTableView.Content = dataTable;
}
private int GetNrOfMultiChartColumns(int itemCount) {
int columns = 0;
if (itemCount <= 2)
columns = 1;
else if (itemCount <= 6)
columns = 2;
else
columns = 3;
return columns;
}
private int GetNrOfMultiChartRows(int itemCount, int columns) {
int rows = 0;
if (columns == 3)
rows = (itemCount + 2) / columns;
else if (columns == 2)
rows = (itemCount + 1) / columns;
else
rows = itemCount / columns;
return rows;
}
private void GenerateMultiChartLayout() {
int checkedItemsCnt = 0;
foreach (var item in Content.VariableItemList.CheckedItems)
checkedItemsCnt++;
// set columns and rows based on number of items
int columns = GetNrOfMultiChartColumns(checkedItemsCnt);
int rows = GetNrOfMultiChartRows(checkedItemsCnt, columns);
tableLayoutPanel.ColumnCount = columns;
tableLayoutPanel.RowCount = rows;
List.Enumerator enumerator = dataTablePerVariable.GetEnumerator();
for (int x = 0; x < columns; x++) {
if (rows <= MAX_TABLE_AUTO_SIZE_ROWS)
tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100 / columns));
else
//scrollbar is shown if there are more than 3 rows -> remove scroll bar width from total width
tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, (tableLayoutPanel.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth) / columns));
for (int y = 0; y < rows; y++) {
//Add a row only when creating the first column
if (x == 0) {
// fixed chart size when there are more than 3 tables
if (rows > MAX_TABLE_AUTO_SIZE_ROWS)
tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, FIXED_CHART_SIZE));
else
tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100 / rows));
}
enumerator.MoveNext();
PreprocessingDataTable d = enumerator.Current;
AddDataTableToTableLayout(d, x, y);
}
}
}
private void AddDataTableToTableLayout(PreprocessingDataTable dataTable, int x, int y) {
PreprocessingDataTableView dataView = new PreprocessingDataTableView();
dataView.Classification = Classification;
dataView.IsDetailedChartViewEnabled = IsDetailedChartViewEnabled;
if (dataTable == null) {
// dummy panel for empty field
Panel p = new Panel();
p.Dock = DockStyle.Fill;
tableLayoutPanel.Controls.Add(p, y, x);
} else {
dataView.Content = dataTable;
dataView.Dock = DockStyle.Fill;
tableLayoutPanel.Controls.Add(dataView, y, x);
}
}
//Remove horizontal scroll bar if visible
private void tableLayoutPanel_Layout(object sender, LayoutEventArgs e) {
if (tableLayoutPanel.HorizontalScroll.Visible) {
// Add padding on the right in order to accomodate the vertical scrollbar
int vWidth = SystemInformation.VerticalScrollBarWidth;
tableLayoutPanel.Padding = new Padding(0, 0, vWidth, 0);
} else {
// Reset padding
tableLayoutPanel.Padding = new Padding(0);
}
}
}
}