using System;
using System.Collections.Generic;
using HeuristicLab.Core;
namespace HeuristicLab.Visualization {
public partial class LineChart : ViewBase {
private readonly IChartDataRowsModel model;
///
/// This constructor shouldn't be called. Only required for the designer.
///
public LineChart() {
InitializeComponent();
}
///
/// Initializes the chart.
///
/// Referenz to the model, for data
public LineChart(IChartDataRowsModel model) : this() {
if (model == null)
throw new NullReferenceException("Model cannot be null.");
//TODO: correct Rectangle to fit
RectangleD clientRectangle = new RectangleD(-1, -1, 11, 11);
canvasUI1.MainCanvas.WorldShape = new WorldShape(clientRectangle, clientRectangle);
this.model = model;
this.Item = (IItem)model;
}
#region Add-/RemoveItemEvents
protected override void AddItemEvents() {
base.AddItemEvents();
model.DataRowAdded += OnDataRowAdded;
model.DataRowRemoved += OnDataRowRemoved;
model.ModelChanged += OnModelChanged;
foreach (IDataRow row in model.Rows) {
OnDataRowAdded(row);
}
}
protected override void RemoveItemEvents() {
base.RemoveItemEvents();
model.DataRowAdded -= OnDataRowAdded;
model.DataRowRemoved -= OnDataRowRemoved;
model.ModelChanged -= OnModelChanged;
}
private void OnDataRowAdded(IDataRow row) {
row.ValueChanged += OnRowValueChanged;
row.ValuesChanged += OnRowValuesChanged;
InitShapes(row);
}
private void InitShapes(IDataRow row) {
List lineShapes = new List();
for (int i = 1; i < row.Count; i++) {
LineShape lineShape = new LineShape(i - 1, row[i - 1], i, row[i], 0, row.Color, row.Thickness);
lineShapes.Add(lineShape);
// TODO each DataRow needs its own WorldShape so Y Axes can be zoomed independently.
canvasUI1.MainCanvas.WorldShape.AddShape(lineShape);
}
rowToLineShapes[row] = lineShapes;
canvasUI1.Invalidate();
}
private void OnDataRowRemoved(IDataRow row) {
row.ValueChanged -= OnRowValueChanged;
row.ValuesChanged -= OnRowValuesChanged;
}
private readonly IDictionary> rowToLineShapes = new Dictionary>();
// TODO use action parameter
private void OnRowValueChanged(IDataRow row, double value, int index, Action action) {
List lineShapes = rowToLineShapes[row];
if (index > lineShapes.Count+1)
throw new NotImplementedException();
// new value was added
if (index > 0 && index == lineShapes.Count+1) {
LineShape lineShape = new LineShape(index - 1, row[index - 1], index, row[index], 0, row.Color, row.Thickness);
lineShapes.Add(lineShape);
// TODO each DataRow needs its own WorldShape so Y Axes can be zoomed independently.
canvasUI1.MainCanvas.WorldShape.AddShape(lineShape);
}
// not the first value
if (index > 0)
lineShapes[index-1].Y2 = value;
// not the last value
if (index > 0 && index < row.Count-1)
lineShapes[index].Y1 = value;
canvasUI1.Invalidate();
}
// TODO use action parameter
private void OnRowValuesChanged(IDataRow row, double[] values, int index, Action action) {
foreach (double value in values) {
OnRowValueChanged(row, value, index++, action);
}
}
private void OnModelChanged() {
}
#endregion
#region Begin-/EndUpdate
private int beginUpdateCount = 0;
public void BeginUpdate() {
beginUpdateCount++;
}
public void EndUpdate() {
if (beginUpdateCount == 0)
throw new InvalidOperationException("Too many EndUpdates.");
beginUpdateCount--;
if (beginUpdateCount == 0)
Invalidate();
}
#endregion
}
}