Index: /trunk/sources/HeuristicLab.Visualization/AvgAggregator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/AvgAggregator.cs	(revision 1325)
+++ /trunk/sources/HeuristicLab.Visualization/AvgAggregator.cs	(revision 1325)
@@ -0,0 +1,192 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace HeuristicLab.Visualization {
+  public class AvgAggregator : IAggregator {
+
+
+    #region IAggregator Members
+
+    public void AddWatch(IDataRow dataRow) {
+      dataRowWatches.Add(dataRow);
+      dataRow.ValueChanged += dataRow_ValueChanged;
+      dataRow.ValuesChanged += dataRow_ValuesChanged;
+      dataRow.DataRowChanged += dataRow_DataRowChanged;
+    }
+
+    public void RemoveWatch(IDataRow dataRow) {
+
+      dataRowWatches.Remove(dataRow);
+      dataRow.DataRowChanged -= dataRow_DataRowChanged;
+      dataRow.ValuesChanged -= dataRow_ValuesChanged;
+      dataRow.ValueChanged -= dataRow_ValueChanged;
+    }
+
+
+    #endregion
+
+    List<IDataRow> dataRowWatches = new List<IDataRow>();
+    double curAvgValue;
+
+    void dataRow_ValueChanged(IDataRow row, double value, int index, Action action) {
+      refreshValue(value);
+    }
+
+    void dataRow_ValuesChanged(IDataRow row, double[] values, int index, Action action) {
+      for (int i = 0; i < values.Length; i++) {
+        refreshValue(values[i]);
+      }
+    }
+
+    void dataRow_DataRowChanged(IDataRow row) {
+      refreshValue(double.MinValue);
+    }
+
+    private void refreshValue(double newVal) {
+      //alle durchlaufen und neues min berechnen; verbesserung: merken in welcher row lowest wert steckt
+
+      curAvgValue = double.MinValue;
+      double tmpSum = 0;
+      int count = 0;
+      foreach (var rows in dataRowWatches) {
+        for (int i = 0; i < rows.Count; i++) {
+          tmpSum += rows[i];
+          count++;
+        }
+      }
+      curAvgValue = tmpSum/count;
+      // evtl nur feuern wenn sich geändert hat (jedes mal?)
+      OnValueChanged(curAvgValue, 0, Action.Modified);
+    }
+
+    #region IDataRow Members
+
+    private string label = "";
+    private Color color = Color.Black;
+    private int thickness = 2;
+    private DrawingStyle style = DrawingStyle.Solid;
+    private DataRowType lineType = DataRowType.Normal;
+
+
+    public string Label {
+      get { return label; }
+      set {
+        label = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public Color Color {
+      get { return color; }
+      set {
+        color = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public int Thickness {
+      get { return thickness; }
+      set {
+        thickness = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public DrawingStyle Style {
+      get { return style; }
+      set {
+        style = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public DataRowType LineType {
+      get { return lineType; }
+      set {
+        lineType = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public LabelProvider.ILabelProvider YAxisLabelProvider {
+      get {
+        throw new NotImplementedException();
+      }
+      set {
+        throw new NotImplementedException();
+      }
+    }
+
+    public void AddValue(double value) {
+      throw new NotSupportedException();
+    }
+
+    public void AddValue(double value, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void AddValues(double[] values) {
+      throw new NotSupportedException();
+    }
+
+    public void AddValues(double[] values, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void ModifyValue(double value, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void ModifyValues(double[] values, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveValue(int index) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveValues(int index, int count) {
+      throw new NotSupportedException();
+    }
+
+    public int Count {
+      get { return 1; }
+    }
+
+    public double this[int index] {
+      get {
+        return curAvgValue;
+      }
+      set {
+        throw new NotSupportedException();
+      }
+    }
+
+    public event ValuesChangedHandler ValuesChanged;
+
+    protected void OnValuesChanged(double[] values, int index, Action action) {
+      if (ValuesChanged != null) {
+        ValuesChanged(this, values, index, action);
+      }
+    }
+
+    public event ValueChangedHandler ValueChanged;
+
+    protected void OnValueChanged(double value, int index, Action action) {
+      if (ValueChanged != null) {
+        ValueChanged(this, value, index, action);
+      }
+    }
+
+    public event DataRowChangedHandler DataRowChanged;
+
+    protected void OnDataRowChanged(IDataRow row) {
+      if (DataRowChanged != null) {
+        DataRowChanged(this);
+      }
+    }
+
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/AvgLineAggregator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/AvgLineAggregator.cs	(revision 1325)
+++ /trunk/sources/HeuristicLab.Visualization/AvgLineAggregator.cs	(revision 1325)
@@ -0,0 +1,206 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace HeuristicLab.Visualization {
+  public class AvgLineAggregator : IAggregator {
+
+    private readonly List<double> dataRow = new List<double>();
+
+    #region IAggregator Members
+
+    public void AddWatch(IDataRow dataRow) {
+      dataRowWatches.Add(dataRow);
+      dataRow.ValueChanged += dataRow_ValueChanged;
+      dataRow.ValuesChanged += dataRow_ValuesChanged;
+      dataRow.DataRowChanged += dataRow_DataRowChanged;
+    }
+
+    public void RemoveWatch(IDataRow dataRow) {
+
+      dataRowWatches.Remove(dataRow);
+      dataRow.DataRowChanged -= dataRow_DataRowChanged;
+      dataRow.ValuesChanged -= dataRow_ValuesChanged;
+      dataRow.ValueChanged -= dataRow_ValueChanged;
+    }
+
+
+    #endregion
+
+    List<IDataRow> dataRowWatches = new List<IDataRow>();
+    
+    void dataRow_ValueChanged(IDataRow row, double value, int index, Action action) {
+      refreshValue(value);
+    }
+
+    void dataRow_ValuesChanged(IDataRow row, double[] values, int index, Action action) {
+      for (int i = 0; i < values.Length; i++) {
+        refreshValue(values[i]);
+      }
+    }
+
+    void dataRow_DataRowChanged(IDataRow row) {
+      refreshValue(double.MinValue);
+    }
+
+    private void refreshValue(double newVal) {
+      //alle durchlaufen und neues min berechnen; verbesserung: merken in welcher row lowest wert steckt
+
+      //curAvgValue = double.MinValue;
+      double tmpSum = 0;
+      int count = dataRowWatches.Count;
+
+      IDataRow firstRow = dataRowWatches[0];
+      int count1 = firstRow.Count;
+      System.Console.WriteLine("count: " + count1);
+
+      dataRow.Clear();
+
+      if (dataRowWatches.Count >= 2) {
+        for (int i = 0; i < count1; i++) {
+          tmpSum = 0;
+          for (int j = 0; j < count; j++) {
+            if (dataRowWatches[j].Count > i) {
+              tmpSum += dataRowWatches[j][i];
+            }
+          }
+
+          this.dataRow.Add(tmpSum/count);
+          OnValueChanged(tmpSum / count, dataRow.Count - 1, Action.Added);
+        }
+      }
+
+      // evtl nur feuern wenn sich geändert hat (jedes mal?)
+      //OnDataRowChanged(this);
+    }
+
+    #region IDataRow Members
+
+    private string label = "";
+    private Color color = Color.Black;
+    private int thickness = 2;
+    private DrawingStyle style = DrawingStyle.Solid;
+    private DataRowType lineType = DataRowType.Normal;
+
+
+    public string Label {
+      get { return label; }
+      set {
+        label = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public Color Color {
+      get { return color; }
+      set {
+        color = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public int Thickness {
+      get { return thickness; }
+      set {
+        thickness = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public DrawingStyle Style {
+      get { return style; }
+      set {
+        style = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public DataRowType LineType {
+      get { return lineType; }
+      set {
+        lineType = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public LabelProvider.ILabelProvider YAxisLabelProvider {
+      get {
+        throw new NotImplementedException();
+      }
+      set {
+        throw new NotImplementedException();
+      }
+    }
+
+    public void AddValue(double value) {
+      dataRow.Add(value);
+      OnValueChanged(value, dataRow.Count - 1, Action.Added);
+    }
+
+    public void AddValue(double value, int index) {
+      throw new System.NotImplementedException();
+    }
+
+    public void AddValues(double[] values) {
+      throw new NotSupportedException();
+    }
+
+    public void AddValues(double[] values, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void ModifyValue(double value, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void ModifyValues(double[] values, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveValue(int index) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveValues(int index, int count) {
+      throw new NotSupportedException();
+    }
+
+    public int Count {
+      get { return dataRowWatches.Count; }
+    }
+
+    public double this[int index] {
+      get { return dataRow[index]; }
+      set {
+        dataRow[index] = value;
+        OnValueChanged(value, index, Action.Modified);
+      }
+    }
+
+    public event ValuesChangedHandler ValuesChanged;
+
+    protected void OnValuesChanged(double[] values, int index, Action action) {
+      if (ValuesChanged != null) {
+        ValuesChanged(this, values, index, action);
+      }
+    }
+
+    public event ValueChangedHandler ValueChanged;
+
+    protected void OnValueChanged(double value, int index, Action action) {
+      if (ValueChanged != null) {
+        ValueChanged(this, value, index, action);
+      }
+    }
+
+    public event DataRowChangedHandler DataRowChanged;
+
+    protected void OnDataRowChanged(IDataRow row) {
+      if (DataRowChanged != null) {
+        DataRowChanged(this);
+      }
+    }
+
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/HeuristicLab.Visualization.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/HeuristicLab.Visualization.csproj	(revision 1324)
+++ /trunk/sources/HeuristicLab.Visualization/HeuristicLab.Visualization.csproj	(revision 1325)
@@ -68,4 +68,6 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="AvgAggregator.cs" />
+    <Compile Include="AvgLineAggregator.cs" />
     <Compile Include="AxisTicks.cs" />
     <Compile Include="Canvas.cs" />
@@ -82,4 +84,5 @@
     <Compile Include="CompositeShape.cs" />
     <Compile Include="ChartDataRowsModelDataCollector.cs" />
+    <Compile Include="IAggregator.cs" />
     <Compile Include="LabelProvider\ContinuousLabelProvider.cs" />
     <Compile Include="LabelProvider\DiscreteLabelProvider.cs" />
@@ -89,4 +92,6 @@
     <Compile Include="IMouseEventListener.cs" />
     <Compile Include="Legend\LegendItem.cs" />
+    <Compile Include="MaxAggregator.cs" />
+    <Compile Include="MinAggregator.cs" />
     <Compile Include="Options\OptionsDialog.cs">
       <SubType>Form</SubType>
Index: /trunk/sources/HeuristicLab.Visualization/IAggregator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/IAggregator.cs	(revision 1325)
+++ /trunk/sources/HeuristicLab.Visualization/IAggregator.cs	(revision 1325)
@@ -0,0 +1,11 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HeuristicLab.Visualization {
+  public interface IAggregator : IDataRow {
+    void AddWatch(IDataRow dataRow);
+    void RemoveWatch(IDataRow dataRow);
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/IDataRow.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/IDataRow.cs	(revision 1324)
+++ /trunk/sources/HeuristicLab.Visualization/IDataRow.cs	(revision 1325)
@@ -7,5 +7,5 @@
     Normal, SingleValue
   }
-  
+
   public interface IDataRow {
     string Label { get; set; }
@@ -19,5 +19,4 @@
     /// Raised when data row data changed. Should cause redraw in the view.
     /// </summary>
-    event DataRowChangedHandler DataRowChanged;
 
     void AddValue(double value);
@@ -40,4 +39,5 @@
     event ValuesChangedHandler ValuesChanged;
     event ValueChangedHandler ValueChanged;
+    event DataRowChangedHandler DataRowChanged;
   }
 }
Index: /trunk/sources/HeuristicLab.Visualization/MaxAggregator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/MaxAggregator.cs	(revision 1325)
+++ /trunk/sources/HeuristicLab.Visualization/MaxAggregator.cs	(revision 1325)
@@ -0,0 +1,195 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace HeuristicLab.Visualization {
+  public class MaxAggregator : IAggregator {
+    
+    
+    #region IAggregator Members
+
+    public void AddWatch(IDataRow dataRow) {
+      dataRowWatches.Add(dataRow);
+      dataRow.ValueChanged += dataRow_ValueChanged;
+      dataRow.ValuesChanged += dataRow_ValuesChanged;
+      dataRow.DataRowChanged += dataRow_DataRowChanged;
+    }
+
+    public void RemoveWatch(IDataRow dataRow) {
+
+      dataRowWatches.Remove(dataRow);
+      dataRow.DataRowChanged -= dataRow_DataRowChanged;
+      dataRow.ValuesChanged -= dataRow_ValuesChanged;
+      dataRow.ValueChanged -= dataRow_ValueChanged;
+    }
+
+
+    #endregion
+
+    List<IDataRow> dataRowWatches = new List<IDataRow>();
+    double curMaxValue;
+
+    void dataRow_ValueChanged(IDataRow row, double value, int index, Action action) {
+      refreshValue(value);
+    }
+
+    void dataRow_ValuesChanged(IDataRow row, double[] values, int index, Action action) {
+      for (int i = 0; i < values.Length; i++) {
+        refreshValue(values[i]);
+      }
+    }
+
+    void dataRow_DataRowChanged(IDataRow row) {
+      refreshValue(double.MinValue);
+    }
+
+    private void refreshValue(double newVal) {
+      //alle durchlaufen und neues min berechnen; verbesserung: merken in welcher row lowest wert steckt
+      if (curMaxValue < newVal) {
+        curMaxValue = newVal;
+        OnValueChanged(newVal, 0, Action.Modified);
+      } else {
+        curMaxValue = double.MinValue;
+        foreach (var rows in dataRowWatches) {
+          for (int i = 0; i < rows.Count; i++) {
+            if (rows[i] > curMaxValue) {
+              curMaxValue = rows[i];
+            }
+          }
+        }
+
+      }
+      // evtl nur feuern wenn sich geändert hat (jedes mal?)
+      OnValueChanged(curMaxValue, 0, Action.Modified);
+    }
+
+    #region IDataRow Members
+
+    private string label = "";
+    private Color color = Color.Black;
+    private int thickness = 2;
+    private DrawingStyle style = DrawingStyle.Solid;
+    private DataRowType lineType = DataRowType.Normal;
+
+
+    public string Label {
+      get { return label; }
+      set {
+        label = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public Color Color {
+      get { return color; }
+      set {
+        color = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public int Thickness {
+      get { return thickness; }
+      set {
+        thickness = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public DrawingStyle Style {
+      get { return style; }
+      set {
+        style = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public DataRowType LineType {
+      get { return lineType; }
+      set {
+        lineType = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public LabelProvider.ILabelProvider YAxisLabelProvider {
+      get {
+        throw new NotImplementedException();
+      }
+      set {
+        throw new NotImplementedException();
+      }
+    }
+
+    public void AddValue(double value) {
+      OnValueChanged(2, 0, Action.Added);
+    }
+
+    public void AddValue(double value, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void AddValues(double[] values) {
+      throw new NotSupportedException();
+    }
+
+    public void AddValues(double[] values, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void ModifyValue(double value, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void ModifyValues(double[] values, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveValue(int index) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveValues(int index, int count) {
+      throw new NotSupportedException();
+    }
+
+    public int Count {
+      get { return 1; }
+    }
+
+    public double this[int index] {
+      get {
+        return curMaxValue;
+      }
+      set {
+        throw new NotSupportedException();
+      }
+    }
+
+    public event ValuesChangedHandler ValuesChanged;
+
+    protected void OnValuesChanged(double[] values, int index, Action action) {
+      if (ValuesChanged != null) {
+        ValuesChanged(this, values, index, action);
+      }
+    }
+
+    public event ValueChangedHandler ValueChanged;
+
+    protected void OnValueChanged(double value, int index, Action action) {
+      if (ValueChanged != null) {
+        ValueChanged(this, value, index, action);
+      }
+    }
+
+    public event DataRowChangedHandler DataRowChanged;
+
+    protected void OnDataRowChanged(IDataRow row) {
+      if (DataRowChanged != null) {
+        DataRowChanged(this);
+      }
+    }
+
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization/MinAggregator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization/MinAggregator.cs	(revision 1325)
+++ /trunk/sources/HeuristicLab.Visualization/MinAggregator.cs	(revision 1325)
@@ -0,0 +1,194 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Drawing;
+using HeuristicLab.Visualization.LabelProvider;
+
+namespace HeuristicLab.Visualization {
+  public class MinAggregator : IAggregator {
+    #region IAggregator Members
+
+    public void AddWatch(IDataRow dataRow) {
+      dataRowWatches.Add(dataRow);
+      dataRow.ValueChanged += dataRow_ValueChanged;
+      dataRow.ValuesChanged += dataRow_ValuesChanged;
+      dataRow.DataRowChanged += dataRow_DataRowChanged;
+    }
+
+    public void RemoveWatch(IDataRow dataRow) {
+
+      dataRowWatches.Remove(dataRow);
+      dataRow.DataRowChanged -= dataRow_DataRowChanged;
+      dataRow.ValuesChanged -= dataRow_ValuesChanged;
+      dataRow.ValueChanged -= dataRow_ValueChanged;
+    }
+
+
+    #endregion
+
+    readonly List<IDataRow> dataRowWatches = new List<IDataRow>();
+    double curMinValue;
+
+    void dataRow_ValueChanged(IDataRow row, double value, int index, Action action) {
+      refreshValue(value);
+    }
+
+    void dataRow_ValuesChanged(IDataRow row, double[] values, int index, Action action) {
+      for (int i = 0; i < values.Length; i++) {
+        refreshValue(values[i]);
+      }
+    }
+
+    void dataRow_DataRowChanged(IDataRow row) {
+      refreshValue(double.MaxValue);
+    }
+
+    private void refreshValue(double newVal) {
+      //alle durchlaufen und neues min berechnen; verbesserung: merken in welcher row lowest wert steckt
+      if (curMinValue > newVal) {
+        curMinValue = newVal;
+        OnValueChanged(newVal, 0, Action.Modified);
+      } else {
+        curMinValue = double.MaxValue;
+        foreach (var rows in dataRowWatches) {
+          for (int i = 0; i < rows.Count; i++) {
+            if (rows[i] < curMinValue) {
+              curMinValue = rows[i];
+            }
+          }
+        }
+
+      }
+      // evtl nur feuern wenn sich geändert hat (jedes mal?)
+      OnValueChanged(curMinValue, 0, Action.Modified);
+    }
+
+    #region IDataRow Members
+
+    private string label = "";
+    private Color color = Color.Black;
+    private int thickness = 2;
+    private DrawingStyle style = DrawingStyle.Solid;
+    private DataRowType lineType = DataRowType.Normal;
+
+
+    public string Label {
+      get { return label; }
+      set {
+        label = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public Color Color {
+      get { return color; }
+      set {
+        color = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public int Thickness {
+      get { return thickness; }
+      set {
+        thickness = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public DrawingStyle Style {
+      get { return style; }
+      set {
+        style = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public DataRowType LineType {
+      get { return lineType; }
+      set {
+        lineType = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    private ILabelProvider labelProvider = new ContinuousLabelProvider("0.##");
+    public ILabelProvider YAxisLabelProvider {
+      get { return labelProvider; }
+      set {
+        this.labelProvider = value;
+        OnDataRowChanged(this);
+      }
+    }
+
+    public void AddValue(double value) {
+      OnValueChanged(2, 0, Action.Added);
+    }
+
+    public void AddValue(double value, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void AddValues(double[] values) {
+      throw new NotSupportedException();
+    }
+
+    public void AddValues(double[] values, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void ModifyValue(double value, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void ModifyValues(double[] values, int index) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveValue(int index) {
+      throw new NotSupportedException();
+    }
+
+    public void RemoveValues(int index, int count) {
+      throw new NotSupportedException();
+    }
+
+    public int Count {
+      get { return 1; }
+    }
+
+    public double this[int index] {
+      get {
+        return curMinValue;
+      }
+      set {
+        throw new NotSupportedException();
+      }
+    }
+
+    public event ValuesChangedHandler ValuesChanged;
+
+    protected void OnValuesChanged(double[] values, int index, Action action) {
+      if (ValuesChanged != null) {
+        ValuesChanged(this, values, index, action);
+      }
+    }
+
+    public event ValueChangedHandler ValueChanged;
+
+    protected void OnValueChanged(double value, int index, Action action) {
+      if (ValueChanged != null) {
+        ValueChanged(this, value, index, action);
+      }
+    }
+
+    public event DataRowChangedHandler DataRowChanged;
+
+    protected void OnDataRowChanged(IDataRow row) {
+      if (DataRowChanged != null) {
+        DataRowChanged(this);
+      }
+    }
+
+    #endregion
+  }
+}
