using System;
using System.Drawing;
using HeuristicLab.Core;
namespace HeuristicLab.Visualization
{
public partial class LineChart : ViewBase
{
private readonly IChartDataRowsModel model;
private Color[] lineColors;
///
/// 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.");
}
this.model = model;
//TODO: read line colors instead of static ones
lineColors = new Color[3];
lineColors[0] = Color.Red;
lineColors[1] = Color.Green;
lineColors[2] = Color.Blue;
//TODO: correct Rectangle to fit
RectangleD clientRectangle = new RectangleD(ClientRectangle.Left, ClientRectangle.Top, ClientRectangle.Right,
ClientRectangle.Bottom);
canvasUI1.MainCanvas.WorldShape = new WorldShape(clientRectangle, clientRectangle);
Reset();
}
///
/// Resets the line chart by deleting all shapes and reloading all data from the model.
///
private void Reset()
{
BeginUpdate();
// TODO clear existing shapes
WorldShape mainWorld = canvasUI1.MainCanvas.WorldShape;
double spacing = mainWorld.BoundingBox.Width/model.Columns.Count;
double oldX = 0;
double currentX = spacing;
ChartDataRowsModelColumn oldColumn = null;
// reload data from the model and create shapes
foreach (ChartDataRowsModelColumn column in model.Columns)
{
if (oldColumn != null)
{
if (column.Values != null)
{
for (int i = 0; i < column.Values.Length; i++)
{
LineShape line = new LineShape(oldX, oldColumn.Values[i], currentX, column.Values[i], 0, lineColors[i]);
mainWorld.AddShape(line);
}
oldX = currentX;
currentX += spacing;
}
oldColumn = column;
}
else
{
oldColumn = column;
}
canvasUI1.Invalidate();
// AddColumn(column.ColumnId, column.Values);
}
EndUpdate();
}
///
/// Event handler which gets called when data in the model changes.
///
/// Type of change
/// Id of the changed column
/// Values contained within the changed column
private void OnDataChanged(ChangeType type, long columnId, double[] values)
{
switch (type)
{
case ChangeType.Add:
AddColumn(columnId, values);
break;
case ChangeType.Modify:
ModifyColumn(columnId, values);
break;
case ChangeType.Remove:
RemoveColumn(columnId);
break;
default:
throw new ArgumentOutOfRangeException("type");
}
}
///
/// Adds a new column to the chart.
///
/// Id of the column
/// Values of the column
private void AddColumn(long columnId, double[] values)
{
throw new NotImplementedException();
}
///
/// Modifies an existing column of the chart.
///
/// Id of the column
/// Values of the column
private void ModifyColumn(long columnId, double[] values)
{
throw new NotImplementedException();
}
///
/// Removes a column from the chart.
///
/// Id of the column
private void RemoveColumn(long columnId)
{
throw new NotImplementedException();
}
#region Add-/RemoveItemEvents
protected override void AddItemEvents()
{
base.AddItemEvents();
model.ColumnChanged += OnDataChanged;
}
protected override void RemoveItemEvents()
{
base.RemoveItemEvents();
model.ColumnChanged -= OnDataChanged;
}
#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
}
}