#region License Information /* HeuristicLab * Copyright (C) 2002-2010 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.Windows.Forms.DataVisualization.Charting; using HeuristicLab.Collections; using HeuristicLab.Core.Views; using HeuristicLab.MainForm; namespace HeuristicLab.Analysis.Views { /// /// The visual representation of a . /// [View("DataTable View")] [Content(typeof(DataTable), true)] public sealed partial class DataTableView : NamedItemView { Dictionary, DataRow> valuesRowsTable; /// /// Gets or sets the variable to represent visually. /// /// Uses property of base class . /// No own data storage present. public new DataTable Content { get { return (DataTable)base.Content; } set { base.Content = value; } } /// /// Initializes a new instance of with caption "Variable". /// public DataTableView() { InitializeComponent(); Caption = "DataTable"; valuesRowsTable = new Dictionary, DataRow>(); } /// /// Removes the eventhandlers from the underlying . /// /// Calls of base class . protected override void DeregisterContentEvents() { foreach (DataRow row in Content.Rows) DeregisterDataRowEvents(row); Content.Rows.ItemsAdded -= new CollectionItemsChangedEventHandler(Rows_ItemsAdded); Content.Rows.ItemsRemoved -= new CollectionItemsChangedEventHandler(Rows_ItemsRemoved); Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler(Rows_ItemsReplaced); Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler(Rows_CollectionReset); base.DeregisterContentEvents(); } /// /// Adds eventhandlers to the underlying . /// /// Calls of base class . protected override void RegisterContentEvents() { base.RegisterContentEvents(); Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler(Rows_ItemsAdded); Content.Rows.ItemsRemoved += new CollectionItemsChangedEventHandler(Rows_ItemsRemoved); Content.Rows.ItemsReplaced += new CollectionItemsChangedEventHandler(Rows_ItemsReplaced); Content.Rows.CollectionReset += new CollectionItemsChangedEventHandler(Rows_CollectionReset); foreach (DataRow row in Content.Rows) RegisterDataRowEvents(row); } protected override void OnContentChanged() { base.OnContentChanged(); chart.Titles.Clear(); chart.Series.Clear(); Caption = "DataTable"; if (Content != null) { Caption = Content.Name + " (" + Content.GetType().Name + ")"; chart.Titles.Add(new Title(Content.Name, Docking.Top)); foreach (DataRow row in Content.Rows) AddDataRow(row); } SetEnabledStateOfControls(); } protected override void OnReadOnlyChanged() { base.OnReadOnlyChanged(); SetEnabledStateOfControls(); } private void SetEnabledStateOfControls() { chart.Enabled = Content != null; } private void AddDataRow(DataRow row) { Series series = new Series(row.Name); series.ChartType = SeriesChartType.FastLine; series.ToolTip = row.Name + " #VAL"; for (int i = 0; i < row.Values.Count; i++) { var value = row.Values[i]; if (IsInvalidValue(value)) { DataPoint point = new DataPoint(); point.IsEmpty = true; series.Points.Add(point); } else { series.Points.Add(value); } } chart.Series.Add(series); } private void RemoveDataRow(DataRow row) { Series series = chart.Series[row.Name]; chart.Series.Remove(series); } #region Content Events private void RegisterDataRowEvents(DataRow row) { row.NameChanged += new EventHandler(Row_NameChanged); valuesRowsTable.Add(row.Values, row); row.Values.ItemsAdded += new CollectionItemsChangedEventHandler>(Values_ItemsAdded); row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler>(Values_ItemsRemoved); row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler>(Values_ItemsReplaced); row.Values.ItemsMoved += new CollectionItemsChangedEventHandler>(Values_ItemsMoved); row.Values.CollectionReset += new CollectionItemsChangedEventHandler>(Values_CollectionReset); } private void DeregisterDataRowEvents(DataRow row) { row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler>(Values_ItemsAdded); row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler>(Values_ItemsRemoved); row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler>(Values_ItemsReplaced); row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler>(Values_ItemsMoved); row.Values.CollectionReset -= new CollectionItemsChangedEventHandler>(Values_CollectionReset); valuesRowsTable.Remove(row.Values); row.NameChanged -= new EventHandler(Row_NameChanged); } protected override void Content_NameChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_NameChanged), sender, e); else { chart.Titles[0].Text = Content.Name; base.Content_NameChanged(sender, e); } } private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler(Rows_ItemsAdded), sender, e); else { foreach (DataRow row in e.Items) { AddDataRow(row); RegisterDataRowEvents(row); } } } private void Rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler(Rows_ItemsRemoved), sender, e); else { foreach (DataRow row in e.Items) { DeregisterDataRowEvents(row); RemoveDataRow(row); } } } private void Rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler(Rows_ItemsReplaced), sender, e); else { foreach (DataRow row in e.OldItems) { DeregisterDataRowEvents(row); RemoveDataRow(row); } foreach (DataRow row in e.Items) { AddDataRow(row); RegisterDataRowEvents(row); } } } private void Rows_CollectionReset(object sender, CollectionItemsChangedEventArgs e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler(Rows_CollectionReset), sender, e); else { foreach (DataRow row in e.OldItems) { DeregisterDataRowEvents(row); RemoveDataRow(row); } foreach (DataRow row in e.Items) { AddDataRow(row); RegisterDataRowEvents(row); } } } private void Row_NameChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Row_NameChanged), sender, e); else { DataRow row = (DataRow)sender; chart.Series[row.Name].Name = row.Name; } } private void Values_ItemsAdded(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler>(Values_ItemsAdded), sender, e); else { DataRow row = null; valuesRowsTable.TryGetValue((IObservableList)sender, out row); if (row != null) { foreach (IndexedItem item in e.Items) { var value = item.Value; if (IsInvalidValue(item.Value)) { DataPoint point = new DataPoint(); point.IsEmpty = true; chart.Series[row.Name].Points.Insert(item.Index, point); } else { chart.Series[row.Name].Points.InsertY(item.Index, value); } } } } } private void Values_ItemsRemoved(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler>(Values_ItemsRemoved), sender, e); else { DataRow row = null; valuesRowsTable.TryGetValue((IObservableList)sender, out row); if (row != null) { List points = new List(); foreach (IndexedItem item in e.Items) points.Add(chart.Series[row.Name].Points[item.Index]); foreach (DataPoint point in points) chart.Series[row.Name].Points.Remove(point); } } } private void Values_ItemsReplaced(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler>(Values_ItemsReplaced), sender, e); else { DataRow row = null; valuesRowsTable.TryGetValue((IObservableList)sender, out row); if (row != null) { foreach (IndexedItem item in e.Items) { if (IsInvalidValue(item.Value)) chart.Series[row.Name].Points[item.Index].IsEmpty = true; else { chart.Series[row.Name].Points[item.Index].YValues = new double[] { item.Value }; chart.Series[row.Name].Points[item.Index].IsEmpty = false; } } } } } private void Values_ItemsMoved(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler>(Values_ItemsMoved), sender, e); else { DataRow row = null; valuesRowsTable.TryGetValue((IObservableList)sender, out row); if (row != null) { foreach (IndexedItem item in e.Items) { if (IsInvalidValue(item.Value)) chart.Series[row.Name].Points[item.Index].IsEmpty = true; else { chart.Series[row.Name].Points[item.Index].YValues = new double[] { item.Value }; chart.Series[row.Name].Points[item.Index].IsEmpty = false; } } } } } private void Values_CollectionReset(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) Invoke(new CollectionItemsChangedEventHandler>(Values_CollectionReset), sender, e); else { DataRow row = null; valuesRowsTable.TryGetValue((IObservableList)sender, out row); if (row != null) { chart.Series[row.Name].Points.Clear(); foreach (IndexedItem item in e.Items) { if (IsInvalidValue(item.Value)) chart.Series[row.Name].Points[item.Index].IsEmpty = true; else { chart.Series[row.Name].Points[item.Index].YValues = new double[] { item.Value }; chart.Series[row.Name].Points[item.Index].IsEmpty = false; } } } } } #endregion private bool IsInvalidValue(double x) { return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue; } } }