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 } }