Index: /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/GradientChart.Designer.cs
===================================================================
--- /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/GradientChart.Designer.cs	(revision 13994)
+++ /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/GradientChart.Designer.cs	(revision 13995)
@@ -42,5 +42,5 @@
       // 
       this.calculationPendingLabel.BackColor = System.Drawing.Color.White;
-      this.calculationPendingLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.Timer;
+      this.calculationPendingLabel.Image = ((System.Drawing.Image)(resources.GetObject("calculationPendingLabel.Image")));
       this.calculationPendingLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
       this.calculationPendingLabel.Location = new System.Drawing.Point(3, 3);
@@ -66,5 +66,5 @@
       verticalLineAnnotation1.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
       verticalLineAnnotation1.Name = "VerticalLineAnnotation";
-      verticalLineAnnotation1.YAxisName = "ChartArea1\\rY";
+      verticalLineAnnotation1.YAxisName = "ChartArea\\rY";
       this.chart.Annotations.Add(verticalLineAnnotation1);
       stripLine1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(223)))), ((int)(((byte)(58)))), ((int)(((byte)(2)))));
@@ -97,5 +97,5 @@
       this.configurationButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
       this.configurationButton.AutoSize = true;
-      this.configurationButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Properties;
+      this.configurationButton.Image = ((System.Drawing.Image)(resources.GetObject("configurationButton.Image")));
       this.configurationButton.Location = new System.Drawing.Point(426, 3);
       this.configurationButton.Name = "configurationButton";
Index: /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/GradientChart.cs
===================================================================
--- /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/GradientChart.cs	(revision 13994)
+++ /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/GradientChart.cs	(revision 13995)
@@ -116,5 +116,7 @@
         if ((value.HasValue && fixedYAxisMin.HasValue && !value.Value.IsAlmost(fixedYAxisMin.Value)) || (value.HasValue != fixedYAxisMin.HasValue)) {
           fixedYAxisMin = value;
-          SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+          // the check below prevents an exception when yMin >= yMax
+          if (yMin < yMax)
+            SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
         }
       }
@@ -126,5 +128,7 @@
         if ((value.HasValue && fixedYAxisMax.HasValue && !value.Value.IsAlmost(fixedYAxisMax.Value)) || (value.HasValue != fixedYAxisMax.HasValue)) {
           fixedYAxisMax = value;
-          SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
+          // the check below prevents an exception when yMin >= yMax
+          if (yMin < yMax)
+            SetupAxis(chart.ChartAreas[0].AxisY, yMin, yMax, YAxisTicks, FixedYAxisMin, FixedYAxisMax);
         }
       }
@@ -258,6 +262,16 @@
 
       // Set cursor and x-axis
+      // Make sure to allow a small offset to be able to distinguish the vertical line annotation from the axis
       var defaultValue = sharedFixedVariables.GetDoubleValue(freeVariable, 0);
-      VerticalLineAnnotation.X = defaultValue;
+      var step = (trainingMax - trainingMin) / drawingSteps;
+      var minimum = chart.ChartAreas[0].AxisX.Minimum;
+      var maximum = chart.ChartAreas[0].AxisX.Maximum;
+      if (defaultValue.IsAlmost(minimum))
+        VerticalLineAnnotation.X = minimum + step;
+      else if (defaultValue.IsAlmost(maximum))
+        VerticalLineAnnotation.X = maximum - step;
+      else
+        VerticalLineAnnotation.X = defaultValue;
+
       if (ShowCursor)
         chart.ChartAreas[0].AxisX.Title = FreeVariable + " : " + defaultValue.ToString("N3", CultureInfo.CurrentCulture);
@@ -379,5 +393,5 @@
         if (ciSeriesCache.TryGetValue(solution, out ciSeries)) {
           var series = seriesCache[solution];
-          ciSeries.Color =  Color.FromArgb(40, series.Color);
+          ciSeries.Color = Color.FromArgb(40, series.Color);
           int idx = chart.Series.IndexOf(seriesCache[solution]);
           chart.Series.Insert(idx, ciSeries);
@@ -484,5 +498,8 @@
 
       await RecalculateAsync();
-    }
+      var args = new EventArgs<IRegressionSolution>(solution);
+      OnSolutionAdded(this, args);
+    }
+
     public async Task RemoveSolutionAsync(IRegressionSolution solution) {
       if (!solutions.Remove(solution))
@@ -495,4 +512,6 @@
 
       await RecalculateAsync();
+      var args = new EventArgs<IRegressionSolution>(solution);
+      OnSolutionRemoved(this, args);
     }
 
@@ -524,4 +543,18 @@
 
     #region Events
+    public event EventHandler<EventArgs<IRegressionSolution>> SolutionAdded;
+    public void OnSolutionAdded(object sender, EventArgs<IRegressionSolution> args) {
+      var added = SolutionAdded;
+      if (added == null) return;
+      added(sender, args);
+    }
+
+    public event EventHandler<EventArgs<IRegressionSolution>> SolutionRemoved;
+    public void OnSolutionRemoved(object sender, EventArgs<IRegressionSolution> args) {
+      var removed = SolutionRemoved;
+      if (removed == null) return;
+      removed(sender, args);
+    }
+
     public event EventHandler VariableValueChanged;
     public void OnVariableValueChanged(object sender, EventArgs args) {
@@ -544,20 +577,14 @@
     }
 
-    private double oldCurserPosition = double.NaN;
     private void chart_AnnotationPositionChanging(object sender, AnnotationPositionChangingEventArgs e) {
       var step = (trainingMax - trainingMin) / drawingSteps;
       double newLocation = step * (long)Math.Round(e.NewLocationX / step);
       var axisX = chart.ChartAreas[0].AxisX;
-      if (newLocation > axisX.Maximum)
-        newLocation = axisX.Maximum;
-      if (newLocation < axisX.Minimum)
-        newLocation = axisX.Minimum;
-
-      if (oldCurserPosition.IsAlmost(newLocation))
-        return;
+      if (newLocation >= axisX.Maximum)
+        newLocation = axisX.Maximum - step;
+      if (newLocation <= axisX.Minimum)
+        newLocation = axisX.Minimum + step;
 
       e.NewLocationX = newLocation;
-      oldCurserPosition = e.NewLocationX;
-
       var annotation = VerticalLineAnnotation;
       var x = annotation.X;
Index: /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.Designer.cs
===================================================================
--- /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.Designer.cs	(revision 13994)
+++ /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.Designer.cs	(revision 13995)
@@ -24,4 +24,5 @@
     /// </summary>
     private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
       this.variableListView = new System.Windows.Forms.ListView();
       this.gradientChartTableLayout = new System.Windows.Forms.TableLayoutPanel();
@@ -33,5 +34,9 @@
       this.configSplitContainer = new System.Windows.Forms.SplitContainer();
       this.variableGroupBox = new System.Windows.Forms.GroupBox();
+      this.layoutGroupBox = new System.Windows.Forms.GroupBox();
+      this.columnsTextBox = new System.Windows.Forms.TextBox();
+      this.columnsLabel = new System.Windows.Forms.Label();
       this.scrollPanel = new System.Windows.Forms.Panel();
+      this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
       this.yAxisConfigGroupBox.SuspendLayout();
       this.densityGroupBox.SuspendLayout();
@@ -41,5 +46,7 @@
       this.configSplitContainer.SuspendLayout();
       this.variableGroupBox.SuspendLayout();
+      this.layoutGroupBox.SuspendLayout();
       this.scrollPanel.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.SuspendLayout();
       // 
@@ -50,5 +57,5 @@
       this.variableListView.Location = new System.Drawing.Point(3, 16);
       this.variableListView.Name = "variableListView";
-      this.variableListView.Size = new System.Drawing.Size(163, 503);
+      this.variableListView.Size = new System.Drawing.Size(163, 458);
       this.variableListView.TabIndex = 0;
       this.variableListView.UseCompatibleStateImageBehavior = false;
@@ -142,4 +149,5 @@
       // 
       this.configSplitContainer.Panel1.Controls.Add(this.variableGroupBox);
+      this.configSplitContainer.Panel1.Controls.Add(this.layoutGroupBox);
       this.configSplitContainer.Panel1.Controls.Add(this.densityGroupBox);
       this.configSplitContainer.Panel1.Controls.Add(this.yAxisConfigGroupBox);
@@ -156,10 +164,40 @@
       this.variableGroupBox.Controls.Add(this.variableListView);
       this.variableGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.variableGroupBox.Location = new System.Drawing.Point(0, 126);
+      this.variableGroupBox.Location = new System.Drawing.Point(0, 171);
       this.variableGroupBox.Name = "variableGroupBox";
-      this.variableGroupBox.Size = new System.Drawing.Size(169, 522);
+      this.variableGroupBox.Size = new System.Drawing.Size(169, 477);
       this.variableGroupBox.TabIndex = 1;
       this.variableGroupBox.TabStop = false;
       this.variableGroupBox.Text = "Variables";
+      // 
+      // layoutGroupBox
+      // 
+      this.layoutGroupBox.Controls.Add(this.columnsTextBox);
+      this.layoutGroupBox.Controls.Add(this.columnsLabel);
+      this.layoutGroupBox.Dock = System.Windows.Forms.DockStyle.Top;
+      this.layoutGroupBox.Location = new System.Drawing.Point(0, 126);
+      this.layoutGroupBox.Name = "layoutGroupBox";
+      this.layoutGroupBox.Size = new System.Drawing.Size(169, 45);
+      this.layoutGroupBox.TabIndex = 5;
+      this.layoutGroupBox.TabStop = false;
+      this.layoutGroupBox.Text = "Layout";
+      // 
+      // columnsTextBox
+      // 
+      this.columnsTextBox.Location = new System.Drawing.Point(66, 17);
+      this.columnsTextBox.Name = "columnsTextBox";
+      this.columnsTextBox.Size = new System.Drawing.Size(94, 20);
+      this.columnsTextBox.TabIndex = 1;
+      this.columnsTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.columnsTextBox_Validating);
+      this.columnsTextBox.Validated += new System.EventHandler(this.columnsTextBox_Validated);
+      // 
+      // columnsLabel
+      // 
+      this.columnsLabel.AutoSize = true;
+      this.columnsLabel.Location = new System.Drawing.Point(7, 20);
+      this.columnsLabel.Name = "columnsLabel";
+      this.columnsLabel.Size = new System.Drawing.Size(50, 13);
+      this.columnsLabel.TabIndex = 0;
+      this.columnsLabel.Text = "Columns:";
       // 
       // scrollPanel
@@ -171,4 +209,8 @@
       this.scrollPanel.Size = new System.Drawing.Size(542, 648);
       this.scrollPanel.TabIndex = 0;
+      // 
+      // errorProvider
+      // 
+      this.errorProvider.ContainerControl = this;
       // 
       // RegressionSolutionTargetResponseGradientView
@@ -187,6 +229,9 @@
       this.configSplitContainer.ResumeLayout(false);
       this.variableGroupBox.ResumeLayout(false);
+      this.layoutGroupBox.ResumeLayout(false);
+      this.layoutGroupBox.PerformLayout();
       this.scrollPanel.ResumeLayout(false);
       this.scrollPanel.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
       this.ResumeLayout(false);
 
@@ -205,4 +250,8 @@
     private System.Windows.Forms.GroupBox variableGroupBox;
     private System.Windows.Forms.Panel scrollPanel;
+    private System.Windows.Forms.GroupBox layoutGroupBox;
+    private System.Windows.Forms.TextBox columnsTextBox;
+    private System.Windows.Forms.Label columnsLabel;
+    private System.Windows.Forms.ErrorProvider errorProvider;
   }
 }
Index: /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.cs
===================================================================
--- /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.cs	(revision 13994)
+++ /branches/HeuristicLab.RegressionSolutionGradientView/HeuristicLab.Problems.DataAnalysis.Views/3.4/Regression/RegressionSolutionTargetResponseGradientView.cs	(revision 13995)
@@ -39,5 +39,5 @@
 
     private const int Points = 200;
-    private const int MaxColumns = 4;
+    private int MaxColumns = 4;
 
     private IEnumerable<string> VisibleVariables {
@@ -66,4 +66,6 @@
       densityComboBox.SelectedIndex = 0; // select None
 
+      columnsTextBox.Text = "4";
+
       // Avoid additional horizontal scrollbar
       var vertScrollWidth = SystemInformation.VerticalScrollBarWidth;
@@ -82,4 +84,5 @@
       limitView.Content.ValueChanged += limit_ValueChanged;
       automaticYAxisCheckBox.CheckedChanged += automaticYAxisCheckBox_CheckedChanged;
+      Content.ModelChanged += solution_ModelChanged;
     }
 
@@ -88,4 +91,5 @@
       limitView.Content.ValueChanged -= limit_ValueChanged;
       automaticYAxisCheckBox.CheckedChanged -= automaticYAxisCheckBox_CheckedChanged;
+      Content.ModelChanged -= solution_ModelChanged;
       base.DeregisterContentEvents();
     }
@@ -171,5 +175,6 @@
       };
       gradientChart.Configure(new[] { Content }, sharedFixedVariables, variableName, Points);
-
+      gradientChart.SolutionAdded += gradientChart_SolutionAdded;
+      gradientChart.SolutionRemoved += gradientChart_SolutionRemoved;
       return gradientChart;
     }
@@ -214,4 +219,41 @@
     }
 
+    private void SetStyles() {
+      var tl = gradientChartTableLayout;
+      tl.RowStyles.Clear();
+      tl.ColumnStyles.Clear();
+      int numVariables = VisibleVariables.Count();
+      if (numVariables == 0)
+        return;
+
+      // set column styles
+      tl.ColumnCount = Math.Min(numVariables, MaxColumns);
+      for (int c = 0; c < tl.ColumnCount; c++)
+        tl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100.0f / tl.ColumnCount));
+
+      // set row styles
+      tl.RowCount = (int)Math.Ceiling((double)numVariables / tl.ColumnCount);
+      var columnWidth = tl.Width / tl.ColumnCount; // assume all columns have the same width
+      var rowHeight = (int)(0.8 * columnWidth);
+      for (int r = 0; r < tl.RowCount; r++)
+        tl.RowStyles.Add(new RowStyle(SizeType.Absolute, rowHeight));
+    }
+
+    private async void gradientChart_SolutionAdded(object sender, EventArgs<IRegressionSolution> e) {
+      var solution = e.Value;
+      foreach (var chart in gradientCharts.Values) {
+        if (sender == chart) continue;
+        await chart.AddSolutionAsync(solution);
+      }
+    }
+
+    private async void gradientChart_SolutionRemoved(object sender, EventArgs<IRegressionSolution> e) {
+      var solution = e.Value;
+      foreach (var chart in gradientCharts.Values) {
+        if (sender == chart) continue;
+        await chart.RemoveSolutionAsync(solution);
+      }
+    }
+
     private async void variableListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
       var item = e.Item;
@@ -223,5 +265,4 @@
 
       tl.SuspendLayout();
-
       if (item.Checked) {
         tl.Controls.Add(chartsPanel);
@@ -234,23 +275,7 @@
       if (tl.Controls.Count > 0) {
         SetupYAxis();
-
         ReOrderControls();
-
-        // set column styles
-        int numVariables = VisibleVariables.Count();
-        tl.ColumnCount = Math.Min(numVariables, MaxColumns);
-        tl.ColumnStyles.Clear();
-        for (int c = 0; c < tl.ColumnCount; c++)
-          tl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100.0f / tl.ColumnCount));
-
-        // set column styles
-        tl.RowCount = (int)Math.Ceiling((double)numVariables / tl.ColumnCount);
-        var columnWidth = tl.Width / tl.ColumnCount; // assume all columns have the same width
-        var rowHeight = (int)(0.8 * columnWidth);
-        tl.RowStyles.Clear();
-        for (int r = 0; r < tl.RowCount; r++)
-          tl.RowStyles.Add(new RowStyle(SizeType.Absolute, rowHeight));
-      }
-
+        SetStyles();
+      }
       tl.ResumeLayout();
     }
@@ -314,5 +339,33 @@
       }
     }
+
+    private void columnsTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      int columns;
+      if (!int.TryParse(columnsTextBox.Text, out columns)) {
+        e.Cancel = true;
+        columnsTextBox.Select();
+        errorProvider.SetError(columnsTextBox, "Columns number must be a positive integer.");
+      }
+    }
+
+    private void columnsTextBox_Validated(object sender, EventArgs e) {
+      errorProvider.SetError(columnsTextBox, "");
+      MaxColumns = int.Parse(columnsTextBox.Text);
+      int columns = Math.Min(VisibleVariables.Count(), MaxColumns);
+      if (columns > 0) {
+        var tl = gradientChartTableLayout;
+        MaxColumns = columns;
+        tl.SuspendLayout();
+        ReOrderControls();
+        SetStyles();
+        tl.ResumeLayout();
+      }
+    }
+
+    private void solution_ModelChanged(object sender, EventArgs e) {
+      OnContentChanged();
+    }
   }
 }
 
+
