Index: branches/HeuristicLab.TimeSeries/HeuristicLab.Analysis.Views/3.3/DataTableView.cs
===================================================================
--- branches/HeuristicLab.TimeSeries/HeuristicLab.Analysis.Views/3.3/DataTableView.cs	(revision 7213)
+++ branches/HeuristicLab.TimeSeries/HeuristicLab.Analysis.Views/3.3/DataTableView.cs	(revision 7268)
@@ -1,5 +1,5 @@
 #region License Information
 /* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
  *
  * This file is part of HeuristicLab.
@@ -31,7 +31,4 @@
 
 namespace HeuristicLab.Analysis.Views {
-  /// <summary>
-  /// The visual representation of a <see cref="Variable"/>.
-  /// </summary>
   [View("DataTable View")]
   [Content(typeof(DataTable), true)]
@@ -39,9 +36,5 @@
     protected List<Series> invisibleSeries;
     protected Dictionary<IObservableList<double>, DataRow> valuesRowsTable;
-    /// <summary>
-    /// Gets or sets the variable to represent visually.
-    /// </summary>
-    /// <remarks>Uses property <see cref="ViewBase.Item"/> of base class <see cref="ViewBase"/>.
-    /// No own data storage present.</remarks>
+
     public new DataTable Content {
       get { return (DataTable)base.Content; }
@@ -49,7 +42,4 @@
     }
 
-    /// <summary>
-    /// Initializes a new instance of <see cref="VariableView"/> with caption "Variable".
-    /// </summary>
     public DataTableView() {
       InitializeComponent();
@@ -61,8 +51,4 @@
 
     #region Event Handler Registration
-    /// <summary>
-    /// Removes the eventhandlers from the underlying <see cref="Variable"/>.
-    /// </summary>
-    /// <remarks>Calls <see cref="ViewBase.RemoveItemEvents"/> of base class <see cref="ViewBase"/>.</remarks>
     protected override void DeregisterContentEvents() {
       foreach (DataRow row in Content.Rows)
@@ -75,9 +61,4 @@
       base.DeregisterContentEvents();
     }
-
-    /// <summary>
-    /// Adds eventhandlers to the underlying <see cref="Variable"/>.
-    /// </summary>
-    /// <remarks>Calls <see cref="ViewBase.AddItemEvents"/> of base class <see cref="ViewBase"/>.</remarks>
     protected override void RegisterContentEvents() {
       base.RegisterContentEvents();
@@ -91,9 +72,4 @@
     }
 
-    /// <summary>
-    /// Automatically called for every existing data row and whenever a data row is added
-    /// to the data table. Do not call this method directly.
-    /// </summary>
-    /// <param name="row">The DataRow that was added.</param>
     protected virtual void RegisterDataRowEvents(DataRow row) {
       row.NameChanged += new EventHandler(Row_NameChanged);
@@ -106,10 +82,4 @@
       row.Values.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
     }
-
-    /// <summary>
-    /// Automatically called for every data row that is removed from the DataTable. Do
-    /// not directly call this method.
-    /// </summary>
-    /// <param name="row">The DataRow that was removed.</param>
     protected virtual void DeregisterDataRowEvents(DataRow row) {
       row.Values.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
@@ -148,13 +118,10 @@
     public void ShowConfiguration() {
       if (Content != null) {
-        DataTableVisualPropertiesDialog dialog = new DataTableVisualPropertiesDialog(Content);
-        dialog.ShowDialog();
+        using (DataTableVisualPropertiesDialog dialog = new DataTableVisualPropertiesDialog(Content)) {
+          dialog.ShowDialog(this);
+        }
       } else MessageBox.Show("Nothing to configure.");
     }
 
-    /// <summary>
-    /// Add the DataRow as a series to the chart.
-    /// </summary>
-    /// <param name="row">DataRow to add as series to the chart.</param>
     protected virtual void AddDataRow(DataRow row) {
       Series series = new Series(row.Name);
@@ -223,4 +190,5 @@
       if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;
       if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;
+      chart.Titles[0].Text = Content.VisualProperties.Title;
 
       if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;
@@ -265,7 +233,4 @@
     }
 
-    /// <summary>
-    /// Set the Y Cursor interval to visible points of enabled series.
-    /// </summary>
     protected virtual void UpdateYCursorInterval() {
       double interestingValuesRange = (
@@ -286,8 +251,4 @@
 
 
-    /// <summary>
-    /// Remove the corresponding series for a certain DataRow.
-    /// </summary>
-    /// <param name="row">DataRow which series should be removed.</param>
     protected virtual void RemoveDataRow(DataRow row) {
       Series series = chart.Series[row.Name];
@@ -577,28 +538,55 @@
       }
 
+      double intervalCenter = intervalWidth / 2;
+
+      double min = 0.0;
+      if (!Double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue) && !Content.VisualProperties.XAxisMinimumAuto)
+        min = Content.VisualProperties.XAxisMinimumFixedValue;
+      else min = minValue;
+
+      double axisInterval = intervalWidth / row.VisualProperties.ScaleFactor;
+
       var area = chart.ChartAreas[0];
-      double current = 0.0;
-      if (!Double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue) && !Content.VisualProperties.XAxisMinimumAuto)
-        current = Content.VisualProperties.XAxisMinimumFixedValue;
-      else current = minValue;
-
-      area.AxisX.Interval = intervalWidth / row.VisualProperties.ScaleFactor;
-      area.AxisX.IntervalOffset = intervalWidth / row.VisualProperties.ScaleFactor;
-
-      series.SetCustomProperty("PointWidth", intervalWidth.ToString());
-
-      int frequency = 0;
-      foreach (double v in row.Values.Where(x => !IsInvalidValue(x)).OrderBy(x => x)) {
-        while (v > current + intervalWidth) {
-          series.Points.AddXY(current + intervalWidth, frequency);
-          current += intervalWidth;
-          frequency = 0;
-        }
-        frequency++;
-      }
-      series.Points.AddXY(current + intervalWidth, frequency);
+      area.AxisX.Interval = axisInterval;
+
+      series.SetCustomProperty("PointWidth", "1"); // 0.8 is the default value
+
+      // get the range or intervals which define the grouping of the frequency values
+      var doubleRange = DoubleRange(min, maxValue + intervalWidth, intervalWidth).Skip(1).ToList();
+
+      // aggregate the row values by unique key and frequency value
+      var valueFrequencies = (from v in row.Values
+                              where !IsInvalidValue(v)
+                              orderby v
+                              group v by v into g
+                              select new Tuple<double, double>(g.First(), g.Count())).ToList();
+
+      // shift the chart to the left so the bars are placed on the intervals
+      if (valueFrequencies.First().Item1 < doubleRange.First())
+        series.Points.Add(new DataPoint(min - intervalWidth, 0));
+
+      // add data points
+      int j = 0;
+      foreach (var d in doubleRange) {
+        double sum = 0.0;
+        // sum the frequency values that fall within the same interval
+        while (j < valueFrequencies.Count && valueFrequencies[j].Item1 < d) {
+          sum += valueFrequencies[j].Item2;
+          ++j;
+        }
+        series.Points.Add(new DataPoint(d - intervalCenter, sum) { ToolTip = "X: [" + (d - intervalWidth) + "-" + d + "), Y: " + sum });
+      }
     }
 
     #region Helpers
+    public static IEnumerable<double> DoubleRange(double min, double max, double step) {
+      double i;
+      for (i = min; i <= max; i += step)
+        yield return i;
+
+      if (i != max + step)
+        yield return i;
+    }
+
     protected void RemoveCustomPropertyIfExists(Series series, string property) {
       if (series.IsCustomPropertySet(property)) series.DeleteCustomProperty(property);
@@ -644,10 +632,4 @@
     }
 
-    /// <summary>
-    /// Determines whether a double value can be displayed (converted to Decimal and not an NaN).
-    /// </summary>
-    /// <param name="x">The number to check.</param>
-    /// <returns><code>true</code> if the value can be safely shwon in the chart,
-    /// <code>false</code> otherwise.</returns>
     protected static bool IsInvalidValue(double x) {
       return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;
