Index: /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.Designer.cs
===================================================================
--- /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.Designer.cs	(revision 12880)
+++ /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.Designer.cs	(revision 12881)
@@ -62,4 +62,8 @@
       this.includeChildrenCheckBox = new System.Windows.Forms.CheckBox();
       this.sizeTrackBar = new System.Windows.Forms.TrackBar();
+      this.yJitterLabel = new System.Windows.Forms.Label();
+      this.xJitterLabel = new System.Windows.Forms.Label();
+      this.yJitterTrackBar = new System.Windows.Forms.TrackBar();
+      this.xJitterTrackBar = new System.Windows.Forms.TrackBar();
       ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
       this.childrenGroupBox.SuspendLayout();
@@ -70,4 +74,6 @@
       ((System.ComponentModel.ISupportInitialize)(this.levelNumericUpDown)).BeginInit();
       ((System.ComponentModel.ISupportInitialize)(this.sizeTrackBar)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.yJitterTrackBar)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.xJitterTrackBar)).BeginInit();
       this.SuspendLayout();
       // 
@@ -85,5 +91,5 @@
       this.xLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
       this.xLabel.AutoSize = true;
-      this.xLabel.Location = new System.Drawing.Point(725, 713);
+      this.xLabel.Location = new System.Drawing.Point(700, 712);
       this.xLabel.Name = "xLabel";
       this.xLabel.Size = new System.Drawing.Size(15, 13);
@@ -107,5 +113,5 @@
       series1.YValuesPerPoint = 2;
       this.chart.Series.Add(series1);
-      this.chart.Size = new System.Drawing.Size(965, 668);
+      this.chart.Size = new System.Drawing.Size(966, 668);
       this.chart.TabIndex = 7;
       this.chart.AxisViewChanged += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.ViewEventArgs>(this.chart_AxisViewChanged);
@@ -117,5 +123,5 @@
       this.yAxisComboBox.Location = new System.Drawing.Point(239, 2);
       this.yAxisComboBox.Name = "yAxisComboBox";
-      this.yAxisComboBox.Size = new System.Drawing.Size(340, 21);
+      this.yAxisComboBox.Size = new System.Drawing.Size(263, 21);
       this.yAxisComboBox.TabIndex = 8;
       this.yAxisComboBox.SelectedValueChanged += new System.EventHandler(this.axisComboBox_SelectedValueChanged);
@@ -126,7 +132,7 @@
       this.xAxisComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
       this.xAxisComboBox.FormattingEnabled = true;
-      this.xAxisComboBox.Location = new System.Drawing.Point(746, 710);
+      this.xAxisComboBox.Location = new System.Drawing.Point(721, 709);
       this.xAxisComboBox.Name = "xAxisComboBox";
-      this.xAxisComboBox.Size = new System.Drawing.Size(340, 21);
+      this.xAxisComboBox.Size = new System.Drawing.Size(249, 21);
       this.xAxisComboBox.TabIndex = 9;
       this.xAxisComboBox.SelectedValueChanged += new System.EventHandler(this.axisComboBox_SelectedValueChanged);
@@ -140,5 +146,5 @@
       this.treeView.Location = new System.Drawing.Point(6, 19);
       this.treeView.Name = "treeView";
-      this.treeView.Size = new System.Drawing.Size(90, 643);
+      this.treeView.Size = new System.Drawing.Size(89, 643);
       this.treeView.TabIndex = 10;
       this.treeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterCheck);
@@ -153,5 +159,5 @@
       this.childrenGroupBox.Location = new System.Drawing.Point(3, 3);
       this.childrenGroupBox.Name = "childrenGroupBox";
-      this.childrenGroupBox.Size = new System.Drawing.Size(102, 668);
+      this.childrenGroupBox.Size = new System.Drawing.Size(101, 668);
       this.childrenGroupBox.TabIndex = 11;
       this.childrenGroupBox.TabStop = false;
@@ -174,5 +180,5 @@
       this.splitContainer.Panel2.Controls.Add(this.chart);
       this.splitContainer.Size = new System.Drawing.Size(1083, 674);
-      this.splitContainer.SplitterDistance = 108;
+      this.splitContainer.SplitterDistance = 107;
       this.splitContainer.TabIndex = 12;
       // 
@@ -242,4 +248,46 @@
       this.sizeTrackBar.ValueChanged += new System.EventHandler(this.sizeTrackBar_ValueChanged);
       // 
+      // yJitterLabel
+      // 
+      this.yJitterLabel.AutoSize = true;
+      this.yJitterLabel.Location = new System.Drawing.Point(509, 6);
+      this.yJitterLabel.Name = "yJitterLabel";
+      this.yJitterLabel.Size = new System.Drawing.Size(32, 13);
+      this.yJitterLabel.TabIndex = 19;
+      this.yJitterLabel.Text = "Jitter:";
+      // 
+      // xJitterLabel
+      // 
+      this.xJitterLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.xJitterLabel.AutoSize = true;
+      this.xJitterLabel.Location = new System.Drawing.Point(977, 712);
+      this.xJitterLabel.Name = "xJitterLabel";
+      this.xJitterLabel.Size = new System.Drawing.Size(32, 13);
+      this.xJitterLabel.TabIndex = 20;
+      this.xJitterLabel.Text = "Jitter:";
+      // 
+      // yJitterTrackBar
+      // 
+      this.yJitterTrackBar.Enabled = false;
+      this.yJitterTrackBar.Location = new System.Drawing.Point(547, 2);
+      this.yJitterTrackBar.Maximum = 100;
+      this.yJitterTrackBar.Name = "yJitterTrackBar";
+      this.yJitterTrackBar.Size = new System.Drawing.Size(65, 45);
+      this.yJitterTrackBar.TabIndex = 21;
+      this.yJitterTrackBar.TickStyle = System.Windows.Forms.TickStyle.None;
+      this.yJitterTrackBar.ValueChanged += new System.EventHandler(this.jitterTrackBar_ValueChanged);
+      // 
+      // xJitterTrackBar
+      // 
+      this.xJitterTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.xJitterTrackBar.Enabled = false;
+      this.xJitterTrackBar.Location = new System.Drawing.Point(1019, 707);
+      this.xJitterTrackBar.Maximum = 100;
+      this.xJitterTrackBar.Name = "xJitterTrackBar";
+      this.xJitterTrackBar.Size = new System.Drawing.Size(65, 45);
+      this.xJitterTrackBar.TabIndex = 22;
+      this.xJitterTrackBar.TickStyle = System.Windows.Forms.TickStyle.None;
+      this.xJitterTrackBar.ValueChanged += new System.EventHandler(this.jitterTrackBar_ValueChanged);
+      // 
       // BubbleChartView
       // 
@@ -248,4 +296,8 @@
       this.BackColor = System.Drawing.SystemColors.Window;
       this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+      this.Controls.Add(this.xJitterTrackBar);
+      this.Controls.Add(this.yJitterTrackBar);
+      this.Controls.Add(this.xJitterLabel);
+      this.Controls.Add(this.yJitterLabel);
       this.Controls.Add(this.sizeTrackBar);
       this.Controls.Add(this.includeChildrenCheckBox);
@@ -269,4 +321,6 @@
       ((System.ComponentModel.ISupportInitialize)(this.levelNumericUpDown)).EndInit();
       ((System.ComponentModel.ISupportInitialize)(this.sizeTrackBar)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.yJitterTrackBar)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.xJitterTrackBar)).EndInit();
       this.ResumeLayout(false);
       this.PerformLayout();
@@ -290,4 +344,8 @@
     private System.Windows.Forms.CheckBox includeChildrenCheckBox;
     private System.Windows.Forms.TrackBar sizeTrackBar;
+    private System.Windows.Forms.Label yJitterLabel;
+    private System.Windows.Forms.Label xJitterLabel;
+    private System.Windows.Forms.TrackBar yJitterTrackBar;
+    private System.Windows.Forms.TrackBar xJitterTrackBar;
   }
 }
Index: /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs
===================================================================
--- /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs	(revision 12880)
+++ /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs	(revision 12881)
@@ -21,5 +21,4 @@
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -44,4 +43,9 @@
     private readonly Dictionary<string, Dictionary<object, double>> categoricalMapping = new Dictionary<string, Dictionary<object, double>>();
 
+    private readonly Dictionary<RecursiveDataItem, double> xJitter = new Dictionary<RecursiveDataItem, double>();
+    private readonly Dictionary<RecursiveDataItem, double> yJitter = new Dictionary<RecursiveDataItem, double>();
+    private readonly Random random = new Random();
+
+
     private string XAxisValue { get { return (string)xAxisComboBox.SelectedItem; } }
     private string YAxisValue { get { return (string)yAxisComboBox.SelectedItem; } }
@@ -49,4 +53,7 @@
 
     private bool updating = false;
+
+    private double xJitterFactor = 0.0;
+    private double yJitterFactor = 0.0;
 
     public new RecursiveDataItem Content {
@@ -78,5 +85,8 @@
       base.SetEnabledStateOfControls();
       levelNumericUpDown.Enabled = Content != null;
-      // ToDo
+      xJitterTrackBar.Enabled = Content != null;
+      yJitterTrackBar.Enabled = Content != null;
+      xAxisComboBox.Enabled = Content != null;
+      yAxisComboBox.Enabled = Content != null;
     }
 
@@ -200,22 +210,34 @@
             AddPoints(xss[i], yss[j], series);
       }
-    }
-    void AddPoints(double[] xs, double[] ys, Series series) {
-      if (xs.Length != ys.Length) return;
-      for (int k = 0; k < xs.Length; k++) {
-        series.Points.Add(new DataPoint(xs[k], new[] { ys[k], 1.0 }));
-      }
-    }
-
-    private List<double[]> GetValues(string key) {
-      var collector = new List<double[]>();
+
+      xJitterTrackBar.Value = 0;
+      yJitterTrackBar.Value = 0;
+
+      //needed to set axis back to automatic and refresh them, otherwise their values may remain NaN
+      var xAxis = chart.ChartAreas[0].AxisX;
+      var yAxis = chart.ChartAreas[0].AxisY;
+      SetAutomaticUpdateOfAxis(xAxis, true);
+      SetAutomaticUpdateOfAxis(yAxis, true);
+      chart.Refresh();
+    }
+    void AddPoints(Tuple<double[], RecursiveDataItem> xs, Tuple<double[], RecursiveDataItem> ys, Series series) {
+      if (xs.Item1.Length != ys.Item1.Length) return;
+      for (int k = 0; k < xs.Item1.Length; k++) {
+        series.Points.Add(new DataPoint(xs.Item1[k], new[] { ys.Item1[k], 1.0 }) {
+          Tag = Tuple.Create(xs.Item1[k], ys.Item1[k], xs.Item2, ys.Item2)
+        });
+      }
+    }
+
+    private List<Tuple<double[], RecursiveDataItem>> GetValues(string key) {
+      var collector = new List<Tuple<double[], RecursiveDataItem>>();
       GetValues(Content, key, collector);
       return collector;
     }
-    private void GetValues(RecursiveDataItem node, string key, List<double[]> collector) {
+    private void GetValues(RecursiveDataItem node, string key, List<Tuple<double[], RecursiveDataItem>> collector) {
       IItem item;
       if (node.Data.TryGetValue(key, out item)) {
         var value = ConvertToDoubles(node, key);
-        collector.Add(value);
+        collector.Add(Tuple.Create(value, node));
       }
 
@@ -437,4 +459,65 @@
       }
     }
+
+    private void UpdateDataPointJitter() {
+      var xAxis = this.chart.ChartAreas[0].AxisX;
+      var yAxis = this.chart.ChartAreas[0].AxisY;
+
+      double xAxisRange = xAxis.Maximum - xAxis.Minimum;
+      double yAxisRange = yAxis.Maximum - yAxis.Minimum;
+
+      foreach (DataPoint point in chart.Series[0].Points) {
+        var tag = (Tuple<double, double, RecursiveDataItem, RecursiveDataItem>)point.Tag;
+        var xItem = tag.Item3;
+        var yItem = tag.Item4;
+        double xValue = tag.Item1;
+        double yValue = tag.Item2;
+
+        if (!xJitterFactor.IsAlmost(0.0))
+          xValue += 0.1 * GetXJitter(xItem) * xJitterFactor * (xAxisRange);
+        if (!yJitterFactor.IsAlmost(0.0))
+          yValue += 0.1 * GetYJitter(yItem) * yJitterFactor * (yAxisRange);
+
+        point.XValue = xValue;
+        point.YValues[0] = yValue;
+      }
+
+      if (xJitterFactor.IsAlmost(0.0) && yJitterFactor.IsAlmost(0.0)) {
+        SetAutomaticUpdateOfAxis(xAxis, true);
+        SetAutomaticUpdateOfAxis(yAxis, true);
+        chart.ChartAreas[0].RecalculateAxesScale();
+      } else {
+        SetAutomaticUpdateOfAxis(xAxis, false);
+        SetAutomaticUpdateOfAxis(yAxis, false);
+      }
+    }
+    private double GetXJitter(RecursiveDataItem item) {
+      if (!this.xJitter.ContainsKey(item))
+        this.xJitter[item] = random.NextDouble() * 2.0 - 1.0;
+      return this.xJitter[item];
+    }
+    private double GetYJitter(RecursiveDataItem item) {
+      if (!this.yJitter.ContainsKey(item))
+        this.yJitter[item] = random.NextDouble() * 2.0 - 1.0;
+      return this.yJitter[item];
+    }
+
+    // sets an axis to automatic or restrains it to its current values
+    // this is used that none of the set values is changed when jitter is applied, so that the chart stays the same
+    private void SetAutomaticUpdateOfAxis(Axis axis, bool enabled) {
+      if (enabled) {
+        axis.Maximum = double.NaN;
+        axis.Minimum = double.NaN;
+        axis.MajorGrid.Interval = double.NaN;
+        axis.MajorTickMark.Interval = double.NaN;
+        axis.LabelStyle.Interval = double.NaN;
+      } else {
+        axis.Minimum = axis.Minimum;
+        axis.Maximum = axis.Maximum;
+        axis.MajorGrid.Interval = axis.MajorGrid.Interval;
+        axis.MajorTickMark.Interval = axis.MajorTickMark.Interval;
+        axis.LabelStyle.Interval = axis.LabelStyle.Interval;
+      }
+    }
     #endregion
 
@@ -480,4 +563,10 @@
       UpdateMarkerSizes();
     }
+
+    private void jitterTrackBar_ValueChanged(object sender, EventArgs e) {
+      this.xJitterFactor = xJitterTrackBar.Value / 100.0;
+      this.yJitterFactor = yJitterTrackBar.Value / 100.0;
+      UpdateDataPointJitter();
+    }
     #endregion
 
