Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/AlleleFrequencyCollectionView.cs	(revision 6342)
@@ -91,5 +91,4 @@
       impacts.YAxisType = AxisType.Secondary;
       chart.Series.Add(impacts);
-      invisibleSeries.Add(impacts);
     }
 
@@ -113,5 +112,5 @@
 
       if (!invisibleSeries.Contains(bestKnown)) {
-        foreach (AlleleFrequency af in Content.Where(x => x.ContainedInBestKnownSolution).OrderBy(x => x.AverageImpact)) {
+        foreach (AlleleFrequency af in Content.Where(x => x.ContainedInBestKnownSolution).OrderBy(x => x.Id)) {
           bestKnown.Points.Add(CreateDataPoint(index, af.Frequency, af));
           if (!invisibleSeries.Contains(qualities)) qualities.Points.Add(CreateDataPoint(index, af.AverageSolutionQuality, af));
@@ -121,5 +120,5 @@
       }
       if (!invisibleSeries.Contains(others)) {
-        foreach (AlleleFrequency af in Content.Where(x => !x.ContainedInBestKnownSolution).OrderBy(x => x.AverageImpact)) {
+        foreach (AlleleFrequency af in Content.Where(x => !x.ContainedInBestKnownSolution).OrderBy(x => x.Id)) {
           others.Points.Add(CreateDataPoint(index, af.Frequency, af));
           if (!invisibleSeries.Contains(qualities)) qualities.Points.Add(CreateDataPoint(index, af.AverageSolutionQuality, af));
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.Designer.cs	(revision 6342)
@@ -0,0 +1,458 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Analysis.Views {
+  partial class DataRowVisualPropertiesControl {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.chartTypeComboBox = new System.Windows.Forms.ComboBox();
+      this.colorDialog = new System.Windows.Forms.ColorDialog();
+      this.colorButton = new System.Windows.Forms.Button();
+      this.startIndexZeroCheckBox = new System.Windows.Forms.CheckBox();
+      this.binsNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.label1 = new System.Windows.Forms.Label();
+      this.label2 = new System.Windows.Forms.Label();
+      this.label3 = new System.Windows.Forms.Label();
+      this.commonGroupBox = new System.Windows.Forms.GroupBox();
+      this.axisGroupBox = new System.Windows.Forms.GroupBox();
+      this.label5 = new System.Windows.Forms.Label();
+      this.label6 = new System.Windows.Forms.Label();
+      this.panel1 = new System.Windows.Forms.Panel();
+      this.yAxisSecondaryRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryRadioButton = new System.Windows.Forms.RadioButton();
+      this.panel2 = new System.Windows.Forms.Panel();
+      this.xAxisPrimaryRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryRadioButton = new System.Windows.Forms.RadioButton();
+      this.histoGramGroupBox = new System.Windows.Forms.GroupBox();
+      this.panel3 = new System.Windows.Forms.Panel();
+      this.binsApproximatelyRadioButton = new System.Windows.Forms.RadioButton();
+      this.binsExactRadioButton = new System.Windows.Forms.RadioButton();
+      this.lineChartGroupBox = new System.Windows.Forms.GroupBox();
+      this.lineWidthNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.label4 = new System.Windows.Forms.Label();
+      this.label7 = new System.Windows.Forms.Label();
+      this.lineStyleComboBox = new System.Windows.Forms.ComboBox();
+      this.label8 = new System.Windows.Forms.Label();
+      ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).BeginInit();
+      this.commonGroupBox.SuspendLayout();
+      this.axisGroupBox.SuspendLayout();
+      this.panel1.SuspendLayout();
+      this.panel2.SuspendLayout();
+      this.histoGramGroupBox.SuspendLayout();
+      this.panel3.SuspendLayout();
+      this.lineChartGroupBox.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.lineWidthNumericUpDown)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chartTypeComboBox
+      // 
+      this.chartTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.chartTypeComboBox.FormattingEnabled = true;
+      this.chartTypeComboBox.Location = new System.Drawing.Point(76, 19);
+      this.chartTypeComboBox.Name = "chartTypeComboBox";
+      this.chartTypeComboBox.Size = new System.Drawing.Size(224, 21);
+      this.chartTypeComboBox.TabIndex = 1;
+      this.chartTypeComboBox.SelectedValueChanged += new System.EventHandler(this.chartTypeComboBox_SelectedValueChanged);
+      // 
+      // colorDialog
+      // 
+      this.colorDialog.Color = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(128)))), ((int)(((byte)(255)))));
+      // 
+      // colorButton
+      // 
+      this.colorButton.BackColor = System.Drawing.SystemColors.Control;
+      this.colorButton.Location = new System.Drawing.Point(76, 46);
+      this.colorButton.Name = "colorButton";
+      this.colorButton.Size = new System.Drawing.Size(23, 23);
+      this.colorButton.TabIndex = 3;
+      this.colorButton.UseVisualStyleBackColor = false;
+      this.colorButton.Click += new System.EventHandler(this.colorButton_Click);
+      // 
+      // startIndexZeroCheckBox
+      // 
+      this.startIndexZeroCheckBox.AutoSize = true;
+      this.startIndexZeroCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.startIndexZeroCheckBox.Location = new System.Drawing.Point(96, 46);
+      this.startIndexZeroCheckBox.Name = "startIndexZeroCheckBox";
+      this.startIndexZeroCheckBox.Size = new System.Drawing.Size(15, 14);
+      this.startIndexZeroCheckBox.TabIndex = 3;
+      this.startIndexZeroCheckBox.UseVisualStyleBackColor = true;
+      this.startIndexZeroCheckBox.CheckedChanged += new System.EventHandler(this.startIndexZeroCheckBox_CheckedChanged);
+      // 
+      // binsNumericUpDown
+      // 
+      this.binsNumericUpDown.Location = new System.Drawing.Point(44, 19);
+      this.binsNumericUpDown.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.binsNumericUpDown.Name = "binsNumericUpDown";
+      this.binsNumericUpDown.Size = new System.Drawing.Size(96, 20);
+      this.binsNumericUpDown.TabIndex = 1;
+      this.binsNumericUpDown.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.binsNumericUpDown.ValueChanged += new System.EventHandler(this.binsNumericUpDown_ValueChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(8, 22);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(62, 13);
+      this.label1.TabIndex = 0;
+      this.label1.Text = "Chart Type:";
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(8, 51);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(34, 13);
+      this.label2.TabIndex = 2;
+      this.label2.Text = "Color:";
+      // 
+      // label3
+      // 
+      this.label3.AutoSize = true;
+      this.label3.Location = new System.Drawing.Point(8, 21);
+      this.label3.Name = "label3";
+      this.label3.Size = new System.Drawing.Size(30, 13);
+      this.label3.TabIndex = 0;
+      this.label3.Text = "Bins:";
+      // 
+      // commonGroupBox
+      // 
+      this.commonGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.commonGroupBox.Controls.Add(this.axisGroupBox);
+      this.commonGroupBox.Controls.Add(this.colorButton);
+      this.commonGroupBox.Controls.Add(this.label1);
+      this.commonGroupBox.Controls.Add(this.label2);
+      this.commonGroupBox.Controls.Add(this.chartTypeComboBox);
+      this.commonGroupBox.Location = new System.Drawing.Point(3, 3);
+      this.commonGroupBox.Name = "commonGroupBox";
+      this.commonGroupBox.Size = new System.Drawing.Size(313, 158);
+      this.commonGroupBox.TabIndex = 0;
+      this.commonGroupBox.TabStop = false;
+      this.commonGroupBox.Text = "Common";
+      // 
+      // axisGroupBox
+      // 
+      this.axisGroupBox.Controls.Add(this.label5);
+      this.axisGroupBox.Controls.Add(this.label6);
+      this.axisGroupBox.Controls.Add(this.panel1);
+      this.axisGroupBox.Controls.Add(this.panel2);
+      this.axisGroupBox.Location = new System.Drawing.Point(6, 75);
+      this.axisGroupBox.Name = "axisGroupBox";
+      this.axisGroupBox.Size = new System.Drawing.Size(299, 75);
+      this.axisGroupBox.TabIndex = 9;
+      this.axisGroupBox.TabStop = false;
+      this.axisGroupBox.Text = "Display Data on";
+      // 
+      // label5
+      // 
+      this.label5.AutoSize = true;
+      this.label5.Location = new System.Drawing.Point(6, 46);
+      this.label5.Name = "label5";
+      this.label5.Size = new System.Drawing.Size(39, 13);
+      this.label5.TabIndex = 6;
+      this.label5.Text = "Y Axis:";
+      // 
+      // label6
+      // 
+      this.label6.AutoSize = true;
+      this.label6.Location = new System.Drawing.Point(6, 22);
+      this.label6.Name = "label6";
+      this.label6.Size = new System.Drawing.Size(39, 13);
+      this.label6.TabIndex = 6;
+      this.label6.Text = "X Axis:";
+      // 
+      // panel1
+      // 
+      this.panel1.Controls.Add(this.yAxisSecondaryRadioButton);
+      this.panel1.Controls.Add(this.yAxisPrimaryRadioButton);
+      this.panel1.Location = new System.Drawing.Point(63, 40);
+      this.panel1.Name = "panel1";
+      this.panel1.Size = new System.Drawing.Size(231, 25);
+      this.panel1.TabIndex = 5;
+      // 
+      // yAxisSecondaryRadioButton
+      // 
+      this.yAxisSecondaryRadioButton.AutoSize = true;
+      this.yAxisSecondaryRadioButton.Location = new System.Drawing.Point(70, 4);
+      this.yAxisSecondaryRadioButton.Name = "yAxisSecondaryRadioButton";
+      this.yAxisSecondaryRadioButton.Size = new System.Drawing.Size(76, 17);
+      this.yAxisSecondaryRadioButton.TabIndex = 1;
+      this.yAxisSecondaryRadioButton.TabStop = true;
+      this.yAxisSecondaryRadioButton.Text = "Secondary";
+      this.yAxisSecondaryRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryRadioButton.CheckedChanged += new System.EventHandler(this.yAxisRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryRadioButton
+      // 
+      this.yAxisPrimaryRadioButton.AutoSize = true;
+      this.yAxisPrimaryRadioButton.Location = new System.Drawing.Point(4, 4);
+      this.yAxisPrimaryRadioButton.Name = "yAxisPrimaryRadioButton";
+      this.yAxisPrimaryRadioButton.Size = new System.Drawing.Size(59, 17);
+      this.yAxisPrimaryRadioButton.TabIndex = 0;
+      this.yAxisPrimaryRadioButton.TabStop = true;
+      this.yAxisPrimaryRadioButton.Text = "Primary";
+      this.yAxisPrimaryRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryRadioButton.CheckedChanged += new System.EventHandler(this.yAxisRadioButton_CheckedChanged);
+      // 
+      // panel2
+      // 
+      this.panel2.Controls.Add(this.xAxisPrimaryRadioButton);
+      this.panel2.Controls.Add(this.xAxisSecondaryRadioButton);
+      this.panel2.Location = new System.Drawing.Point(63, 16);
+      this.panel2.Name = "panel2";
+      this.panel2.Size = new System.Drawing.Size(231, 25);
+      this.panel2.TabIndex = 7;
+      // 
+      // xAxisPrimaryRadioButton
+      // 
+      this.xAxisPrimaryRadioButton.AutoSize = true;
+      this.xAxisPrimaryRadioButton.Location = new System.Drawing.Point(4, 4);
+      this.xAxisPrimaryRadioButton.Name = "xAxisPrimaryRadioButton";
+      this.xAxisPrimaryRadioButton.Size = new System.Drawing.Size(59, 17);
+      this.xAxisPrimaryRadioButton.TabIndex = 0;
+      this.xAxisPrimaryRadioButton.TabStop = true;
+      this.xAxisPrimaryRadioButton.Text = "Primary";
+      this.xAxisPrimaryRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryRadioButton.CheckedChanged += new System.EventHandler(this.xAxisRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryRadioButton
+      // 
+      this.xAxisSecondaryRadioButton.AutoSize = true;
+      this.xAxisSecondaryRadioButton.Location = new System.Drawing.Point(70, 4);
+      this.xAxisSecondaryRadioButton.Name = "xAxisSecondaryRadioButton";
+      this.xAxisSecondaryRadioButton.Size = new System.Drawing.Size(76, 17);
+      this.xAxisSecondaryRadioButton.TabIndex = 1;
+      this.xAxisSecondaryRadioButton.TabStop = true;
+      this.xAxisSecondaryRadioButton.Text = "Secondary";
+      this.xAxisSecondaryRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryRadioButton.CheckedChanged += new System.EventHandler(this.xAxisRadioButton_CheckedChanged);
+      // 
+      // histoGramGroupBox
+      // 
+      this.histoGramGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.histoGramGroupBox.Controls.Add(this.panel3);
+      this.histoGramGroupBox.Controls.Add(this.binsNumericUpDown);
+      this.histoGramGroupBox.Controls.Add(this.label3);
+      this.histoGramGroupBox.Location = new System.Drawing.Point(3, 269);
+      this.histoGramGroupBox.Name = "histoGramGroupBox";
+      this.histoGramGroupBox.Size = new System.Drawing.Size(313, 49);
+      this.histoGramGroupBox.TabIndex = 2;
+      this.histoGramGroupBox.TabStop = false;
+      this.histoGramGroupBox.Text = "Histogram";
+      // 
+      // panel3
+      // 
+      this.panel3.Controls.Add(this.binsApproximatelyRadioButton);
+      this.panel3.Controls.Add(this.binsExactRadioButton);
+      this.panel3.Location = new System.Drawing.Point(146, 16);
+      this.panel3.Name = "panel3";
+      this.panel3.Size = new System.Drawing.Size(154, 25);
+      this.panel3.TabIndex = 2;
+      // 
+      // binsApproximatelyRadioButton
+      // 
+      this.binsApproximatelyRadioButton.AutoSize = true;
+      this.binsApproximatelyRadioButton.Location = new System.Drawing.Point(4, 4);
+      this.binsApproximatelyRadioButton.Name = "binsApproximatelyRadioButton";
+      this.binsApproximatelyRadioButton.Size = new System.Drawing.Size(90, 17);
+      this.binsApproximatelyRadioButton.TabIndex = 0;
+      this.binsApproximatelyRadioButton.TabStop = true;
+      this.binsApproximatelyRadioButton.Text = "Approximately";
+      this.binsApproximatelyRadioButton.UseVisualStyleBackColor = true;
+      this.binsApproximatelyRadioButton.CheckedChanged += new System.EventHandler(this.binNumberRadioButton_CheckedChanged);
+      // 
+      // binsExactRadioButton
+      // 
+      this.binsExactRadioButton.AutoSize = true;
+      this.binsExactRadioButton.Location = new System.Drawing.Point(100, 4);
+      this.binsExactRadioButton.Name = "binsExactRadioButton";
+      this.binsExactRadioButton.Size = new System.Drawing.Size(52, 17);
+      this.binsExactRadioButton.TabIndex = 1;
+      this.binsExactRadioButton.TabStop = true;
+      this.binsExactRadioButton.Text = "Exact";
+      this.binsExactRadioButton.UseVisualStyleBackColor = true;
+      this.binsExactRadioButton.CheckedChanged += new System.EventHandler(this.binNumberRadioButton_CheckedChanged);
+      // 
+      // lineChartGroupBox
+      // 
+      this.lineChartGroupBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.lineChartGroupBox.Controls.Add(this.lineWidthNumericUpDown);
+      this.lineChartGroupBox.Controls.Add(this.label4);
+      this.lineChartGroupBox.Controls.Add(this.startIndexZeroCheckBox);
+      this.lineChartGroupBox.Controls.Add(this.label7);
+      this.lineChartGroupBox.Controls.Add(this.lineStyleComboBox);
+      this.lineChartGroupBox.Controls.Add(this.label8);
+      this.lineChartGroupBox.Location = new System.Drawing.Point(3, 167);
+      this.lineChartGroupBox.Name = "lineChartGroupBox";
+      this.lineChartGroupBox.Size = new System.Drawing.Size(313, 96);
+      this.lineChartGroupBox.TabIndex = 1;
+      this.lineChartGroupBox.TabStop = false;
+      this.lineChartGroupBox.Text = "Line Chart";
+      // 
+      // lineWidthNumericUpDown
+      // 
+      this.lineWidthNumericUpDown.Location = new System.Drawing.Point(96, 66);
+      this.lineWidthNumericUpDown.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.lineWidthNumericUpDown.Name = "lineWidthNumericUpDown";
+      this.lineWidthNumericUpDown.Size = new System.Drawing.Size(65, 20);
+      this.lineWidthNumericUpDown.TabIndex = 5;
+      this.lineWidthNumericUpDown.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.lineWidthNumericUpDown.ValueChanged += new System.EventHandler(this.lineWidthNumericUpDown_ValueChanged);
+      // 
+      // label4
+      // 
+      this.label4.AutoSize = true;
+      this.label4.Location = new System.Drawing.Point(8, 68);
+      this.label4.Name = "label4";
+      this.label4.Size = new System.Drawing.Size(61, 13);
+      this.label4.TabIndex = 4;
+      this.label4.Text = "Line Width:";
+      // 
+      // label7
+      // 
+      this.label7.AutoSize = true;
+      this.label7.Location = new System.Drawing.Point(8, 46);
+      this.label7.Name = "label7";
+      this.label7.Size = new System.Drawing.Size(82, 13);
+      this.label7.TabIndex = 2;
+      this.label7.Text = "Start Index at 0:";
+      // 
+      // lineStyleComboBox
+      // 
+      this.lineStyleComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.lineStyleComboBox.FormattingEnabled = true;
+      this.lineStyleComboBox.Location = new System.Drawing.Point(96, 19);
+      this.lineStyleComboBox.Name = "lineStyleComboBox";
+      this.lineStyleComboBox.Size = new System.Drawing.Size(204, 21);
+      this.lineStyleComboBox.TabIndex = 1;
+      this.lineStyleComboBox.SelectedValueChanged += new System.EventHandler(this.lineStyleComboBox_SelectedValueChanged);
+      // 
+      // label8
+      // 
+      this.label8.AutoSize = true;
+      this.label8.Location = new System.Drawing.Point(8, 22);
+      this.label8.Name = "label8";
+      this.label8.Size = new System.Drawing.Size(56, 13);
+      this.label8.TabIndex = 0;
+      this.label8.Text = "Line Style:";
+      // 
+      // DataRowVisualPropertiesControl
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.lineChartGroupBox);
+      this.Controls.Add(this.histoGramGroupBox);
+      this.Controls.Add(this.commonGroupBox);
+      this.Name = "DataRowVisualPropertiesControl";
+      this.Size = new System.Drawing.Size(319, 323);
+      ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).EndInit();
+      this.commonGroupBox.ResumeLayout(false);
+      this.commonGroupBox.PerformLayout();
+      this.axisGroupBox.ResumeLayout(false);
+      this.axisGroupBox.PerformLayout();
+      this.panel1.ResumeLayout(false);
+      this.panel1.PerformLayout();
+      this.panel2.ResumeLayout(false);
+      this.panel2.PerformLayout();
+      this.histoGramGroupBox.ResumeLayout(false);
+      this.histoGramGroupBox.PerformLayout();
+      this.panel3.ResumeLayout(false);
+      this.panel3.PerformLayout();
+      this.lineChartGroupBox.ResumeLayout(false);
+      this.lineChartGroupBox.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.lineWidthNumericUpDown)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.ComboBox chartTypeComboBox;
+    private System.Windows.Forms.ColorDialog colorDialog;
+    private System.Windows.Forms.Button colorButton;
+    private System.Windows.Forms.CheckBox startIndexZeroCheckBox;
+    private System.Windows.Forms.NumericUpDown binsNumericUpDown;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.Label label3;
+    private System.Windows.Forms.GroupBox commonGroupBox;
+    private System.Windows.Forms.GroupBox histoGramGroupBox;
+    private System.Windows.Forms.RadioButton xAxisSecondaryRadioButton;
+    private System.Windows.Forms.RadioButton yAxisSecondaryRadioButton;
+    private System.Windows.Forms.RadioButton xAxisPrimaryRadioButton;
+    private System.Windows.Forms.RadioButton yAxisPrimaryRadioButton;
+    private System.Windows.Forms.Label label6;
+    private System.Windows.Forms.GroupBox lineChartGroupBox;
+    private System.Windows.Forms.NumericUpDown lineWidthNumericUpDown;
+    private System.Windows.Forms.Label label4;
+    private System.Windows.Forms.Label label7;
+    private System.Windows.Forms.RadioButton binsExactRadioButton;
+    private System.Windows.Forms.RadioButton binsApproximatelyRadioButton;
+    private System.Windows.Forms.Panel panel2;
+    private System.Windows.Forms.Panel panel1;
+    private System.Windows.Forms.Panel panel3;
+    private System.Windows.Forms.ComboBox lineStyleComboBox;
+    private System.Windows.Forms.Label label8;
+    private System.Windows.Forms.Label label5;
+    private System.Windows.Forms.GroupBox axisGroupBox;
+  }
+}
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.cs	(revision 6342)
@@ -0,0 +1,172 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("DataRow Visual Properties")]
+  public partial class DataRowVisualPropertiesControl : UserControl {
+    protected bool SuppressEvents { get; set; }
+
+    private DataRowVisualProperties content;
+    public DataRowVisualProperties Content {
+      get { return content; }
+      set {
+        bool changed = (value != content);
+        content = value;
+        if (changed) OnContentChanged();
+      }
+    }
+
+    public DataRowVisualPropertiesControl() {
+      InitializeComponent();
+      chartTypeComboBox.DataSource = Enum.GetValues(typeof(DataRowVisualProperties.DataRowChartType));
+      lineStyleComboBox.DataSource = Enum.GetValues(typeof(DataRowVisualProperties.DataRowLineStyle));
+    }
+
+    protected virtual void OnContentChanged() {
+      SuppressEvents = true;
+      try {
+        if (Content == null) {
+          chartTypeComboBox.SelectedIndex = -1;
+          colorButton.BackColor = SystemColors.Control;
+          colorButton.Text = "?";
+          yAxisPrimaryRadioButton.Checked = false;
+          yAxisSecondaryRadioButton.Checked = false;
+          xAxisPrimaryRadioButton.Checked = false;
+          xAxisSecondaryRadioButton.Checked = false;
+          lineStyleComboBox.SelectedIndex = -1;
+          startIndexZeroCheckBox.Checked = false;
+          lineWidthNumericUpDown.Value = 1;
+          binsNumericUpDown.Value = 1;
+          binsApproximatelyRadioButton.Checked = false;
+          binsExactRadioButton.Checked = false;
+        } else {
+          chartTypeComboBox.SelectedItem = Content.ChartType;
+          if (Content.Color.IsEmpty) {
+            colorButton.BackColor = SystemColors.Control;
+            colorButton.Text = "?";
+          } else {
+            colorButton.BackColor = Content.Color;
+            colorButton.Text = String.Empty;
+          }
+          yAxisPrimaryRadioButton.Checked = !Content.SecondYAxis;
+          yAxisSecondaryRadioButton.Checked = Content.SecondYAxis;
+          xAxisPrimaryRadioButton.Checked = !Content.SecondXAxis;
+          xAxisSecondaryRadioButton.Checked = Content.SecondXAxis;
+          lineStyleComboBox.SelectedItem = Content.LineStyle;
+          startIndexZeroCheckBox.Checked = Content.StartIndexZero;
+          lineWidthNumericUpDown.Value = Content.LineWidth;
+          binsNumericUpDown.Value = Content.Bins;
+          binsApproximatelyRadioButton.Checked = !Content.ExactBins;
+          binsExactRadioButton.Checked = Content.ExactBins;
+        }
+      } finally { SuppressEvents = false; }
+      SetEnabledStateOfControls();
+    }
+
+    protected virtual void SetEnabledStateOfControls() {
+      commonGroupBox.Enabled = Content != null;
+      lineChartGroupBox.Enabled = Content != null && Content.ChartType == DataRowVisualProperties.DataRowChartType.Line;
+      histoGramGroupBox.Enabled = Content != null && Content.ChartType == DataRowVisualProperties.DataRowChartType.Histogram;
+    }
+
+    #region Event Handlers
+    private void chartTypeComboBox_SelectedValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        DataRowVisualProperties.DataRowChartType selected = (DataRowVisualProperties.DataRowChartType)chartTypeComboBox.SelectedValue;
+        Content.ChartType = selected;
+        if (Content.ChartType != selected) {
+          MessageBox.Show("There may be incompatibilities with other series or the data is not suited to be displayed as " + selected.ToString() + ".", "Failed to set type to " + selected.ToString());
+          SuppressEvents = true;
+          try {
+            chartTypeComboBox.SelectedItem = Content.ChartType;
+          } finally { SuppressEvents = false; }
+        }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void colorButton_Click(object sender, EventArgs e) {
+      if (colorDialog.ShowDialog() == DialogResult.OK) {
+        Content.Color = colorDialog.Color;
+        colorButton.BackColor = Content.Color;
+        colorButton.Text = String.Empty;
+      }
+    }
+
+    private void yAxisRadioButton_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondYAxis = yAxisSecondaryRadioButton.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void xAxisRadioButton_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondXAxis = xAxisSecondaryRadioButton.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+
+    private void lineStyleComboBox_SelectedValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.LineStyle = (DataRowVisualProperties.DataRowLineStyle)lineStyleComboBox.SelectedValue;
+      }
+    }
+
+    private void startIndexZeroCheckBox_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.StartIndexZero = startIndexZeroCheckBox.Checked;
+      }
+    }
+
+    private void lineWidthNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.LineWidth = (int)lineWidthNumericUpDown.Value;
+      }
+    }
+
+    private void binsNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.Bins = (int)binsNumericUpDown.Value;
+      }
+    }
+
+    private void binNumberRadioButton_CheckedChanged(object sender, EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.ExactBins = binsExactRadioButton.Checked;
+        } finally { SuppressEvents = false; }
+      }
+    }
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.resx
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.resx	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataRowVisualPropertiesControl.resx	(revision 6342)
@@ -0,0 +1,123 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="colorDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableHistoryView.cs	(revision 6342)
@@ -27,9 +27,25 @@
   [View("DataTableHistory View")]
   [Content(typeof(DataTableHistory), true)]
-  public partial class DataTableHistoryView : MovieView<DataTable> {
+  public partial class DataTableHistoryView : MovieView<DataTable>, IConfigureableView {
     public DataTableHistoryView() {
       InitializeComponent();
       itemsGroupBox.Text = "Data Table";
     }
+
+    public void ShowConfiguration() {
+      DataTable current = viewHost.Content as DataTable;
+      if (current == null) return;
+      using (DataTableVisualPropertiesDialog dialog = new DataTableVisualPropertiesDialog(current)) {
+        if (dialog.ShowDialog() != DialogResult.OK) return;
+        foreach (DataTable dt in Content) {
+          if (current != dt) {
+            dt.VisualProperties = (DataTableVisualProperties)current.VisualProperties.Clone();
+            foreach (DataRow row in current.Rows)
+              dt.Rows[row.Name].VisualProperties = (DataRowVisualProperties)row.VisualProperties.Clone();
+          }
+        }
+      }
+    }
+
   }
 }
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.cs	(revision 6342)
@@ -36,5 +36,5 @@
   [View("DataTable View")]
   [Content(typeof(DataTable), true)]
-  public partial class DataTableView : NamedItemView {
+  public partial class DataTableView : NamedItemView, IConfigureableView {
     protected List<Series> invisibleSeries;
     protected Dictionary<IObservableList<double>, DataRow> valuesRowsTable;
@@ -60,4 +60,5 @@
     }
 
+    #region Event Handler Registration
     /// <summary>
     /// Removes the eventhandlers from the underlying <see cref="Variable"/>.
@@ -89,4 +90,37 @@
         RegisterDataRowEvents(row);
     }
+
+    /// <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);
+      row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
+      valuesRowsTable.Add(row.Values, row);
+      row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
+      row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
+      row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
+      row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
+      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);
+      row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
+      row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
+      row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
+      row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
+      valuesRowsTable.Remove(row.Values);
+      row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);
+      row.NameChanged -= new EventHandler(Row_NameChanged);
+    }
+    #endregion
 
     protected override void OnContentChanged() {
@@ -102,7 +136,6 @@
         foreach (DataRow row in Content.Rows)
           AddDataRow(row);
-        chart.ChartAreas[0].AxisX.Title = Content.VisualProperties.XAxisTitle;
-        chart.ChartAreas[0].AxisY.Title = Content.VisualProperties.YAxisTitle;
-        chart.ChartAreas[0].AxisY2.Title = Content.VisualProperties.SecondYAxisTitle;
+        ConfigureChartArea(chart.ChartAreas[0]);
+        RecalculateAxesScale(chart.ChartAreas[0]);
       }
     }
@@ -113,4 +146,10 @@
     }
 
+    public void ShowConfiguration() {
+      if (Content != null) {
+        DataTableVisualPropertiesDialog dialog = new DataTableVisualPropertiesDialog(Content);
+        dialog.ShowDialog();
+      } else MessageBox.Show("Nothing to configure.");
+    }
 
     /// <summary>
@@ -120,10 +159,37 @@
     protected virtual void AddDataRow(DataRow row) {
       Series series = new Series(row.Name);
+      ConfigureSeries(series, row);
+      FillSeriesWithRowValues(series, row);
+
+      chart.Series.Add(series);
+      ConfigureChartArea(chart.ChartAreas[0]);
+      RecalculateAxesScale(chart.ChartAreas[0]);
+      UpdateYCursorInterval();
+    }
+
+    private void ConfigureSeries(Series series, DataRow row) {
+      RemoveCustomPropertyIfExists(series, "PointWidth");
+      series.BorderWidth = 1;
+      series.BorderDashStyle = ChartDashStyle.Solid;
+      series.BorderColor = Color.Empty;
+
+      if (row.VisualProperties.Color != Color.Empty)
+        series.Color = row.VisualProperties.Color;
+      else series.Color = Color.Empty;
+
       switch (row.VisualProperties.ChartType) {
         case DataRowVisualProperties.DataRowChartType.Line:
           series.ChartType = SeriesChartType.FastLine;
+          series.BorderWidth = row.VisualProperties.LineWidth;
+          series.BorderDashStyle = ConvertLineStyle(row.VisualProperties.LineStyle);
           break;
         case DataRowVisualProperties.DataRowChartType.Bars:
-          series.ChartType = SeriesChartType.Bar;
+          // Bar is incompatible with anything but Bar and StackedBar*
+          if (!chart.Series.Any(x => x.ChartType != SeriesChartType.Bar && x.ChartType != SeriesChartType.StackedBar && x.ChartType != SeriesChartType.StackedBar100))
+            series.ChartType = SeriesChartType.Bar;
+          else {
+            series.ChartType = SeriesChartType.FastPoint; //default
+            row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Points;
+          }
           break;
         case DataRowVisualProperties.DataRowChartType.Columns:
@@ -133,4 +199,11 @@
           series.ChartType = SeriesChartType.FastPoint;
           break;
+        case DataRowVisualProperties.DataRowChartType.Histogram:
+          series.ChartType = SeriesChartType.Column;
+          series.SetCustomProperty("PointWidth", "1");
+          if (!series.Color.IsEmpty && series.Color.GetBrightness() < 0.25)
+            series.BorderColor = Color.White;
+          else series.BorderColor = Color.Black;
+          break;
         default:
           series.ChartType = SeriesChartType.FastPoint;
@@ -138,12 +211,52 @@
       }
       series.YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary;
-      if (row.VisualProperties.Color != Color.Empty) series.Color = row.VisualProperties.Color;
+      series.XAxisType = row.VisualProperties.SecondXAxis ? AxisType.Secondary : AxisType.Primary;
       series.ToolTip = row.Name + " X = #INDEX, Y = #VAL";
-      FillSeriesWithRowValues(series, row);
-      chart.Series.Add(series);
-      chart.ChartAreas[0].RecalculateAxesScale();
-      UpdateYCursorInterval();
-    }
-
+    }
+
+    private void ConfigureChartArea(ChartArea area) {
+      if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;
+      if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisX.Title = Content.VisualProperties.XAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisX2.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX2.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisX2.Title = Content.VisualProperties.SecondXAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisY.Title = Content.VisualProperties.YAxisTitle;
+
+      if (Content.VisualProperties.AxisTitleFont != null) area.AxisY2.TitleFont = Content.VisualProperties.AxisTitleFont;
+      if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY2.TitleForeColor = Content.VisualProperties.AxisTitleColor;
+      area.AxisY2.Title = Content.VisualProperties.SecondYAxisTitle;
+    }
+
+    private void RecalculateAxesScale(ChartArea area) {
+      // Reset the axes bounds so that RecalculateAxesScale() will assign new bounds
+      foreach (Axis a in area.Axes) {
+        a.Minimum = double.NaN;
+        a.Maximum = double.NaN;
+      }
+      area.RecalculateAxesScale();
+      area.AxisX.IsMarginVisible = false;
+      area.AxisX2.IsMarginVisible = false;
+
+      if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue;
+      if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue;
+      if (!Content.VisualProperties.SecondXAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMinimumFixedValue)) area.AxisX2.Minimum = Content.VisualProperties.SecondXAxisMinimumFixedValue;
+      if (!Content.VisualProperties.SecondXAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondXAxisMaximumFixedValue)) area.AxisX2.Maximum = Content.VisualProperties.SecondXAxisMaximumFixedValue;
+      if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue;
+      if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue;
+      if (!Content.VisualProperties.SecondYAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMinimumFixedValue)) area.AxisY2.Minimum = Content.VisualProperties.SecondYAxisMinimumFixedValue;
+      if (!Content.VisualProperties.SecondYAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.SecondYAxisMaximumFixedValue)) area.AxisY2.Maximum = Content.VisualProperties.SecondYAxisMaximumFixedValue;
+      if (area.AxisX.Minimum > area.AxisX.Maximum) area.AxisX.Maximum = area.AxisX.Minimum + 1;
+      if (area.AxisX2.Minimum > area.AxisX2.Maximum) area.AxisX2.Maximum = area.AxisX2.Minimum + 1;
+      if (area.AxisY.Minimum > area.AxisY.Maximum) area.AxisY.Maximum = area.AxisY.Minimum + 1;
+      if (area.AxisY2.Minimum > area.AxisY2.Maximum) area.AxisY2.Maximum = area.AxisY2.Minimum + 1;
+    }
 
     /// <summary>
@@ -151,15 +264,14 @@
     /// </summary>
     protected virtual void UpdateYCursorInterval() {
-      double interestingValuesRange = (from series in chart.Series
-                                       where series.Enabled
-                                       let values = (from point in series.Points
-                                                     where !point.IsEmpty
-                                                     select point.YValues[0])
-                                                     .DefaultIfEmpty(1.0)
-                                       let range = values.Max() - values.Min()
-                                       where range > 0.0
-                                       select range)
-                                       .DefaultIfEmpty(1.0)
-                                       .Min();
+      double interestingValuesRange = (
+        from series in chart.Series
+        where series.Enabled
+        let values = (from point in series.Points
+                      where !point.IsEmpty
+                      select point.YValues[0]).DefaultIfEmpty(1.0)
+        let range = values.Max() - values.Min()
+        where range > 0.0
+        select range
+        ).DefaultIfEmpty(1.0).Min();
 
       double digits = (int)Math.Log10(interestingValuesRange) - 3;
@@ -178,39 +290,9 @@
       if (invisibleSeries.Contains(series))
         invisibleSeries.Remove(series);
-      chart.ChartAreas[0].RecalculateAxesScale();
-    }
-
-    #region Content Events
-    /// <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);
-      row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
-      valuesRowsTable.Add(row.Values, row);
-      row.Values.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsAdded);
-      row.Values.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
-      row.Values.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
-      row.Values.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
-      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);
-      row.Values.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsRemoved);
-      row.Values.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsReplaced);
-      row.Values.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_ItemsMoved);
-      row.Values.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<double>>(Values_CollectionReset);
-      valuesRowsTable.Remove(row.Values);
-      row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);
-      row.NameChanged -= new EventHandler(Row_NameChanged);
-    }
+      RecalculateAxesScale(chart.ChartAreas[0]);
+    }
+
+    #region Event Handlers
+    #region Content Event Handlers
     protected override void Content_NameChanged(object sender, EventArgs e) {
       if (InvokeRequired)
@@ -225,9 +307,10 @@
         Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e);
       else {
-        chart.ChartAreas[0].AxisX.Title = Content.VisualProperties.XAxisTitle;
-        chart.ChartAreas[0].AxisY.Title = Content.VisualProperties.YAxisTitle;
-        chart.ChartAreas[0].AxisY2.Title = Content.VisualProperties.SecondYAxisTitle;
-      }
-    }
+        ConfigureChartArea(chart.ChartAreas[0]);
+        RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed
+      }
+    }
+    #endregion
+    #region Rows Event Handlers
     private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<DataRow> e) {
       if (InvokeRequired)
@@ -278,4 +361,6 @@
       }
     }
+    #endregion
+    #region Row Event Handlers
     private void Row_VisualPropertiesChanged(object sender, EventArgs e) {
       if (InvokeRequired)
@@ -283,24 +368,9 @@
       else {
         DataRow row = (DataRow)sender;
-        switch (row.VisualProperties.ChartType) {
-          case DataRowVisualProperties.DataRowChartType.Line:
-            chart.Series[row.Name].ChartType = SeriesChartType.FastLine;
-            break;
-          case DataRowVisualProperties.DataRowChartType.Bars:
-            chart.Series[row.Name].ChartType = SeriesChartType.Bar;
-            break;
-          case DataRowVisualProperties.DataRowChartType.Columns:
-            chart.Series[row.Name].ChartType = SeriesChartType.Column;
-            break;
-          case DataRowVisualProperties.DataRowChartType.Points:
-            chart.Series[row.Name].ChartType = SeriesChartType.FastPoint;
-            break;
-          default:
-            chart.Series[row.Name].ChartType = SeriesChartType.FastPoint;
-            break;
-        }
-        chart.Series[row.Name].YAxisType = row.VisualProperties.SecondYAxis ? AxisType.Secondary : AxisType.Primary;
-        if (row.VisualProperties.Color != Color.Empty) chart.Series[row.Name].Color = row.VisualProperties.Color;
-        chart.ChartAreas[0].RecalculateAxesScale();
+        Series series = chart.Series[row.Name];
+        series.Points.Clear();
+        ConfigureSeries(series, row);
+        FillSeriesWithRowValues(series, row);
+        RecalculateAxesScale(chart.ChartAreas[0]);
       }
     }
@@ -313,4 +383,6 @@
       }
     }
+    #endregion
+    #region Values Event Handlers
     private void Values_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<double>> e) {
       if (InvokeRequired)
@@ -324,4 +396,5 @@
             rowSeries.Points.Clear();
             FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
             UpdateYCursorInterval();
           }
@@ -340,4 +413,5 @@
             rowSeries.Points.Clear();
             FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
             UpdateYCursorInterval();
           }
@@ -354,12 +428,18 @@
           Series rowSeries = chart.Series[row.Name];
           if (!invisibleSeries.Contains(rowSeries)) {
-            foreach (IndexedItem<double> item in e.Items) {
-              if (IsInvalidValue(item.Value))
-                rowSeries.Points[item.Index].IsEmpty = true;
-              else {
-                rowSeries.Points[item.Index].YValues = new double[] { item.Value };
-                rowSeries.Points[item.Index].IsEmpty = false;
+            if (row.VisualProperties.ChartType == DataRowVisualProperties.DataRowChartType.Histogram) {
+              rowSeries.Points.Clear();
+              FillSeriesWithRowValues(rowSeries, row);
+            } else {
+              foreach (IndexedItem<double> item in e.Items) {
+                if (IsInvalidValue(item.Value))
+                  rowSeries.Points[item.Index].IsEmpty = true;
+                else {
+                  rowSeries.Points[item.Index].YValues = new double[] { item.Value };
+                  rowSeries.Points[item.Index].IsEmpty = false;
+                }
               }
             }
+            RecalculateAxesScale(chart.ChartAreas[0]);
             UpdateYCursorInterval();
           }
@@ -378,4 +458,5 @@
             rowSeries.Points.Clear();
             FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
             UpdateYCursorInterval();
           }
@@ -395,4 +476,5 @@
             rowSeries.Points.Clear();
             FillSeriesWithRowValues(rowSeries, row);
+            RecalculateAxesScale(chart.ChartAreas[0]);
             UpdateYCursorInterval();
           }
@@ -401,6 +483,7 @@
     }
     #endregion
-
-    #region Chart Events
+    #endregion
+
+    #region Chart Event Handlers
     private void chart_MouseDown(object sender, MouseEventArgs e) {
       HitTestResult result = chart.HitTest(e.X, e.Y);
@@ -409,4 +492,23 @@
       }
     }
+    private void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = chart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem)
+        this.Cursor = Cursors.Hand;
+      else
+        this.Cursor = Cursors.Default;
+    }
+    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
+      foreach (LegendItem legendItem in e.LegendItems) {
+        var series = chart.Series[legendItem.SeriesName];
+        if (series != null) {
+          bool seriesIsInvisible = invisibleSeries.Contains(series);
+          foreach (LegendCell cell in legendItem.Cells) {
+            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
+          }
+        }
+      }
+    }
+    #endregion
 
     private void ToggleSeriesVisible(Series series) {
@@ -423,4 +525,5 @@
           FillSeriesWithRowValues(series, row);
           this.chart.Legends[series.Legend].ForeColor = Color.Black;
+          RecalculateAxesScale(chart.ChartAreas[0]);
           UpdateYCursorInterval();
         }
@@ -429,36 +532,102 @@
 
     private void FillSeriesWithRowValues(Series series, DataRow row) {
-      for (int i = 0; i < row.Values.Count; i++) {
-        var value = row.Values[i];
-        DataPoint point = new DataPoint();
-        point.XValue = row.VisualProperties.StartIndexZero ? i : i + 1;
-        if (IsInvalidValue(value))
-          point.IsEmpty = true;
-        else
-          point.YValues = new double[] { value };
-        series.Points.Add(point);
-      }
-    }
-
-    private void chart_MouseMove(object sender, MouseEventArgs e) {
-      HitTestResult result = chart.HitTest(e.X, e.Y);
-      if (result.ChartElementType == ChartElementType.LegendItem)
-        this.Cursor = Cursors.Hand;
-      else
-        this.Cursor = Cursors.Default;
-    }
-    private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
-      foreach (LegendItem legendItem in e.LegendItems) {
-        var series = chart.Series[legendItem.SeriesName];
-        if (series != null) {
-          bool seriesIsInvisible = invisibleSeries.Contains(series);
-          foreach (LegendCell cell in legendItem.Cells) {
-            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
-          }
-        }
-      }
-    }
-    #endregion
-
+      switch (row.VisualProperties.ChartType) {
+        case DataRowVisualProperties.DataRowChartType.Histogram:
+          CalculateHistogram(series, row);
+          break;
+        default: {
+            for (int i = 0; i < row.Values.Count; i++) {
+              var value = row.Values[i];
+              DataPoint point = new DataPoint();
+              point.XValue = row.VisualProperties.StartIndexZero ? i : i + 1;
+              if (IsInvalidValue(value))
+                point.IsEmpty = true;
+              else
+                point.YValues = new double[] { value };
+              series.Points.Add(point);
+            }
+          }
+          break;
+      }
+    }
+
+    protected virtual void CalculateHistogram(Series series, DataRow row) {
+      series.Points.Clear();
+      if (!row.Values.Any()) return;
+      int bins = row.VisualProperties.Bins;
+
+      double minValue = row.Values.Min();
+      double maxValue = row.Values.Max();
+      double intervalWidth = (maxValue - minValue) / bins;
+      if (intervalWidth < 0) return;
+      if (intervalWidth == 0) {
+        series.Points.AddXY(minValue, row.Values.Count);
+        return;
+      }
+
+      if (!row.VisualProperties.ExactBins) {
+        intervalWidth = HumanRoundRange(intervalWidth);
+        minValue = Math.Floor(minValue / intervalWidth) * intervalWidth;
+        maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth;
+      }
+
+      double current = minValue, intervalCenter = intervalWidth / 2.0;
+      int frequency = 0;
+      series.Points.AddXY(current - intervalCenter, 0); // so that the first column is not visually truncated
+      foreach (double v in row.Values.Where(x => !IsInvalidValue(x)).OrderBy(x => x)) {
+        while (v > current + intervalWidth) {
+          series.Points.AddXY(current + intervalCenter, frequency);
+          current += intervalWidth;
+          frequency = 0;
+        }
+        frequency++;
+      }
+      series.Points.AddXY(current + intervalCenter, frequency);
+      series.Points.AddXY(current + 3 * intervalCenter, 0); // so that the last column is not visually truncated
+    }
+
+    #region Helpers
+    protected void RemoveCustomPropertyIfExists(Series series, string property) {
+      if (series.IsCustomPropertySet(property)) series.DeleteCustomProperty(property);
+    }
+
+    private double HumanRoundRange(double range) {
+      double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range)));
+      double rounding = range / base10;
+      if (rounding <= 1.5) rounding = 1;
+      else if (rounding <= 2.25) rounding = 2;
+      else if (rounding <= 3.75) rounding = 2.5;
+      else if (rounding <= 7.5) rounding = 5;
+      else rounding = 10;
+      return rounding * base10;
+    }
+
+    private double HumanRoundMax(double max) {
+      double base10;
+      if (max > 0) base10 = Math.Pow(10.0, Math.Floor(Math.Log10(max)));
+      else base10 = Math.Pow(10.0, Math.Ceiling(Math.Log10(-max)));
+      double rounding = (max > 0) ? base10 : -base10;
+      while (rounding < max) rounding += base10;
+      return rounding;
+    }
+
+    private ChartDashStyle ConvertLineStyle(DataRowVisualProperties.DataRowLineStyle dataRowLineStyle) {
+      switch (dataRowLineStyle) {
+        case DataRowVisualProperties.DataRowLineStyle.Dash:
+          return ChartDashStyle.Dash;
+        case DataRowVisualProperties.DataRowLineStyle.DashDot:
+          return ChartDashStyle.DashDot;
+        case DataRowVisualProperties.DataRowLineStyle.DashDotDot:
+          return ChartDashStyle.DashDotDot;
+        case DataRowVisualProperties.DataRowLineStyle.Dot:
+          return ChartDashStyle.Dot;
+        case DataRowVisualProperties.DataRowLineStyle.NotSet:
+          return ChartDashStyle.NotSet;
+        case DataRowVisualProperties.DataRowLineStyle.Solid:
+          return ChartDashStyle.Solid;
+        default:
+          return ChartDashStyle.NotSet;
+      }
+    }
 
     /// <summary>
@@ -471,4 +640,5 @@
       return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;
     }
+    #endregion
   }
 }
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.resx
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.resx	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableView.resx	(revision 6342)
@@ -0,0 +1,126 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>107, 17</value>
+  </metadata>
+  <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.Designer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.Designer.cs	(revision 6342)
@@ -0,0 +1,903 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Analysis.Views {
+  partial class DataTableVisualPropertiesControl {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+      this.label1 = new System.Windows.Forms.Label();
+      this.yAxisPrimaryTitleTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisSecondaryTitleTextBox = new System.Windows.Forms.TextBox();
+      this.label4 = new System.Windows.Forms.Label();
+      this.xAxisPrimaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.label12 = new System.Windows.Forms.Label();
+      this.label9 = new System.Windows.Forms.Label();
+      this.xAxisPrimaryTitleTextBox = new System.Windows.Forms.TextBox();
+      this.label11 = new System.Windows.Forms.Label();
+      this.xAxisPrimaryMaximumPanel = new System.Windows.Forms.Panel();
+      this.xAxisPrimaryMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.xAxisPrimaryMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisPrimaryMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisPrimaryMinimumPanel = new System.Windows.Forms.Panel();
+      this.xAxisPrimaryMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.xAxisPrimaryMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisPrimaryMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.label10 = new System.Windows.Forms.Label();
+      this.xAxisSecondaryTitleTextBox = new System.Windows.Forms.TextBox();
+      this.label5 = new System.Windows.Forms.Label();
+      this.label6 = new System.Windows.Forms.Label();
+      this.xAxisSecondaryMaximumPanel = new System.Windows.Forms.Panel();
+      this.xAxisSecondaryMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.xAxisSecondaryMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryMinimumPanel = new System.Windows.Forms.Panel();
+      this.xAxisSecondaryMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.xAxisSecondaryMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.xAxisSecondaryMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.axisTabControl = new System.Windows.Forms.TabControl();
+      this.mainTabPage = new System.Windows.Forms.TabPage();
+      this.axisFontLabel = new System.Windows.Forms.Label();
+      this.titleFontLabel = new System.Windows.Forms.Label();
+      this.axisFontButton = new System.Windows.Forms.Button();
+      this.label3 = new System.Windows.Forms.Label();
+      this.titleFontButton = new System.Windows.Forms.Button();
+      this.label2 = new System.Windows.Forms.Label();
+      this.xAxisTabPage = new System.Windows.Forms.TabPage();
+      this.yAxisTabPage = new System.Windows.Forms.TabPage();
+      this.yAxisSecondaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.label13 = new System.Windows.Forms.Label();
+      this.label14 = new System.Windows.Forms.Label();
+      this.yAxisSecondaryMaximumPanel = new System.Windows.Forms.Panel();
+      this.yAxisSecondaryMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisSecondaryMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisSecondaryMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisSecondaryMinimumPanel = new System.Windows.Forms.Panel();
+      this.yAxisSecondaryMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisSecondaryMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisSecondaryMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryGroupBox = new System.Windows.Forms.GroupBox();
+      this.label7 = new System.Windows.Forms.Label();
+      this.label8 = new System.Windows.Forms.Label();
+      this.yAxisPrimaryMaximumPanel = new System.Windows.Forms.Panel();
+      this.yAxisPrimaryMaximumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisPrimaryMaximumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryMaximumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryMinimumPanel = new System.Windows.Forms.Panel();
+      this.yAxisPrimaryMinimumFixedTextBox = new System.Windows.Forms.TextBox();
+      this.yAxisPrimaryMinimumFixedRadioButton = new System.Windows.Forms.RadioButton();
+      this.yAxisPrimaryMinimumAutoRadioButton = new System.Windows.Forms.RadioButton();
+      this.errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
+      this.titleFontDialog = new System.Windows.Forms.FontDialog();
+      this.axisFontDialog = new System.Windows.Forms.FontDialog();
+      this.xAxisPrimaryGroupBox.SuspendLayout();
+      this.xAxisPrimaryMaximumPanel.SuspendLayout();
+      this.xAxisPrimaryMinimumPanel.SuspendLayout();
+      this.xAxisSecondaryGroupBox.SuspendLayout();
+      this.xAxisSecondaryMaximumPanel.SuspendLayout();
+      this.xAxisSecondaryMinimumPanel.SuspendLayout();
+      this.axisTabControl.SuspendLayout();
+      this.mainTabPage.SuspendLayout();
+      this.xAxisTabPage.SuspendLayout();
+      this.yAxisTabPage.SuspendLayout();
+      this.yAxisSecondaryGroupBox.SuspendLayout();
+      this.yAxisSecondaryMaximumPanel.SuspendLayout();
+      this.yAxisSecondaryMinimumPanel.SuspendLayout();
+      this.yAxisPrimaryGroupBox.SuspendLayout();
+      this.yAxisPrimaryMaximumPanel.SuspendLayout();
+      this.yAxisPrimaryMinimumPanel.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(4, 26);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(30, 13);
+      this.label1.TabIndex = 0;
+      this.label1.Text = "Title:";
+      // 
+      // yAxisPrimaryTitleTextBox
+      // 
+      this.yAxisPrimaryTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisPrimaryTitleTextBox.Location = new System.Drawing.Point(63, 23);
+      this.yAxisPrimaryTitleTextBox.Name = "yAxisPrimaryTitleTextBox";
+      this.yAxisPrimaryTitleTextBox.Size = new System.Drawing.Size(221, 20);
+      this.yAxisPrimaryTitleTextBox.TabIndex = 1;
+      this.yAxisPrimaryTitleTextBox.Validated += new System.EventHandler(this.yPrimaryTitleTextBox_Validated);
+      // 
+      // yAxisSecondaryTitleTextBox
+      // 
+      this.yAxisSecondaryTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.yAxisSecondaryTitleTextBox.Location = new System.Drawing.Point(63, 23);
+      this.yAxisSecondaryTitleTextBox.Name = "yAxisSecondaryTitleTextBox";
+      this.yAxisSecondaryTitleTextBox.Size = new System.Drawing.Size(243, 20);
+      this.yAxisSecondaryTitleTextBox.TabIndex = 1;
+      this.yAxisSecondaryTitleTextBox.Validated += new System.EventHandler(this.ySecondaryTitleTextBox_Validated);
+      // 
+      // label4
+      // 
+      this.label4.AutoSize = true;
+      this.label4.Location = new System.Drawing.Point(4, 26);
+      this.label4.Name = "label4";
+      this.label4.Size = new System.Drawing.Size(30, 13);
+      this.label4.TabIndex = 0;
+      this.label4.Text = "Title:";
+      // 
+      // xAxisPrimaryGroupBox
+      // 
+      this.xAxisPrimaryGroupBox.Controls.Add(this.label12);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.label9);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.xAxisPrimaryTitleTextBox);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.label11);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.xAxisPrimaryMaximumPanel);
+      this.xAxisPrimaryGroupBox.Controls.Add(this.xAxisPrimaryMinimumPanel);
+      this.xAxisPrimaryGroupBox.Location = new System.Drawing.Point(6, 6);
+      this.xAxisPrimaryGroupBox.Name = "xAxisPrimaryGroupBox";
+      this.xAxisPrimaryGroupBox.Size = new System.Drawing.Size(316, 107);
+      this.xAxisPrimaryGroupBox.TabIndex = 0;
+      this.xAxisPrimaryGroupBox.TabStop = false;
+      this.xAxisPrimaryGroupBox.Text = "Primary Axis";
+      // 
+      // label12
+      // 
+      this.label12.AutoSize = true;
+      this.label12.Location = new System.Drawing.Point(4, 77);
+      this.label12.Name = "label12";
+      this.label12.Size = new System.Drawing.Size(54, 13);
+      this.label12.TabIndex = 4;
+      this.label12.Text = "Maximum:";
+      // 
+      // label9
+      // 
+      this.label9.AutoSize = true;
+      this.label9.Location = new System.Drawing.Point(4, 26);
+      this.label9.Name = "label9";
+      this.label9.Size = new System.Drawing.Size(30, 13);
+      this.label9.TabIndex = 0;
+      this.label9.Text = "Title:";
+      // 
+      // xAxisPrimaryTitleTextBox
+      // 
+      this.xAxisPrimaryTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisPrimaryTitleTextBox.Location = new System.Drawing.Point(63, 23);
+      this.xAxisPrimaryTitleTextBox.Name = "xAxisPrimaryTitleTextBox";
+      this.xAxisPrimaryTitleTextBox.Size = new System.Drawing.Size(221, 20);
+      this.xAxisPrimaryTitleTextBox.TabIndex = 1;
+      this.xAxisPrimaryTitleTextBox.Validated += new System.EventHandler(this.xPrimaryTitleTextBox_Validated);
+      // 
+      // label11
+      // 
+      this.label11.AutoSize = true;
+      this.label11.Location = new System.Drawing.Point(4, 53);
+      this.label11.Name = "label11";
+      this.label11.Size = new System.Drawing.Size(51, 13);
+      this.label11.TabIndex = 2;
+      this.label11.Text = "Minimum:";
+      // 
+      // xAxisPrimaryMaximumPanel
+      // 
+      this.xAxisPrimaryMaximumPanel.Controls.Add(this.xAxisPrimaryMaximumFixedTextBox);
+      this.xAxisPrimaryMaximumPanel.Controls.Add(this.xAxisPrimaryMaximumFixedRadioButton);
+      this.xAxisPrimaryMaximumPanel.Controls.Add(this.xAxisPrimaryMaximumAutoRadioButton);
+      this.xAxisPrimaryMaximumPanel.Location = new System.Drawing.Point(63, 71);
+      this.xAxisPrimaryMaximumPanel.Name = "xAxisPrimaryMaximumPanel";
+      this.xAxisPrimaryMaximumPanel.Size = new System.Drawing.Size(245, 25);
+      this.xAxisPrimaryMaximumPanel.TabIndex = 5;
+      // 
+      // xAxisPrimaryMaximumFixedTextBox
+      // 
+      this.xAxisPrimaryMaximumFixedTextBox.Location = new System.Drawing.Point(126, 2);
+      this.xAxisPrimaryMaximumFixedTextBox.Name = "xAxisPrimaryMaximumFixedTextBox";
+      this.xAxisPrimaryMaximumFixedTextBox.Size = new System.Drawing.Size(95, 20);
+      this.xAxisPrimaryMaximumFixedTextBox.TabIndex = 2;
+      this.xAxisPrimaryMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisPrimaryMaximumFixedTextBox_Validating);
+      // 
+      // xAxisPrimaryMaximumFixedRadioButton
+      // 
+      this.xAxisPrimaryMaximumFixedRadioButton.AutoSize = true;
+      this.xAxisPrimaryMaximumFixedRadioButton.Location = new System.Drawing.Point(70, 4);
+      this.xAxisPrimaryMaximumFixedRadioButton.Name = "xAxisPrimaryMaximumFixedRadioButton";
+      this.xAxisPrimaryMaximumFixedRadioButton.Size = new System.Drawing.Size(50, 17);
+      this.xAxisPrimaryMaximumFixedRadioButton.TabIndex = 1;
+      this.xAxisPrimaryMaximumFixedRadioButton.TabStop = true;
+      this.xAxisPrimaryMaximumFixedRadioButton.Text = "Fixed";
+      this.xAxisPrimaryMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisPrimaryMaximumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMaximumAutoRadioButton
+      // 
+      this.xAxisPrimaryMaximumAutoRadioButton.AutoSize = true;
+      this.xAxisPrimaryMaximumAutoRadioButton.Location = new System.Drawing.Point(4, 4);
+      this.xAxisPrimaryMaximumAutoRadioButton.Name = "xAxisPrimaryMaximumAutoRadioButton";
+      this.xAxisPrimaryMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisPrimaryMaximumAutoRadioButton.TabIndex = 0;
+      this.xAxisPrimaryMaximumAutoRadioButton.TabStop = true;
+      this.xAxisPrimaryMaximumAutoRadioButton.Text = "Auto";
+      this.xAxisPrimaryMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisPrimaryMaximumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMinimumPanel
+      // 
+      this.xAxisPrimaryMinimumPanel.Controls.Add(this.xAxisPrimaryMinimumFixedTextBox);
+      this.xAxisPrimaryMinimumPanel.Controls.Add(this.xAxisPrimaryMinimumFixedRadioButton);
+      this.xAxisPrimaryMinimumPanel.Controls.Add(this.xAxisPrimaryMinimumAutoRadioButton);
+      this.xAxisPrimaryMinimumPanel.Location = new System.Drawing.Point(63, 47);
+      this.xAxisPrimaryMinimumPanel.Name = "xAxisPrimaryMinimumPanel";
+      this.xAxisPrimaryMinimumPanel.Size = new System.Drawing.Size(245, 25);
+      this.xAxisPrimaryMinimumPanel.TabIndex = 3;
+      // 
+      // xAxisPrimaryMinimumFixedTextBox
+      // 
+      this.xAxisPrimaryMinimumFixedTextBox.Location = new System.Drawing.Point(126, 2);
+      this.xAxisPrimaryMinimumFixedTextBox.Name = "xAxisPrimaryMinimumFixedTextBox";
+      this.xAxisPrimaryMinimumFixedTextBox.Size = new System.Drawing.Size(95, 20);
+      this.xAxisPrimaryMinimumFixedTextBox.TabIndex = 2;
+      this.xAxisPrimaryMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisPrimaryMinimumFixedTextBox_Validating);
+      // 
+      // xAxisPrimaryMinimumFixedRadioButton
+      // 
+      this.xAxisPrimaryMinimumFixedRadioButton.AutoSize = true;
+      this.xAxisPrimaryMinimumFixedRadioButton.Location = new System.Drawing.Point(70, 3);
+      this.xAxisPrimaryMinimumFixedRadioButton.Name = "xAxisPrimaryMinimumFixedRadioButton";
+      this.xAxisPrimaryMinimumFixedRadioButton.Size = new System.Drawing.Size(50, 17);
+      this.xAxisPrimaryMinimumFixedRadioButton.TabIndex = 1;
+      this.xAxisPrimaryMinimumFixedRadioButton.TabStop = true;
+      this.xAxisPrimaryMinimumFixedRadioButton.Text = "Fixed";
+      this.xAxisPrimaryMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisPrimaryMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisPrimaryMinimumAutoRadioButton
+      // 
+      this.xAxisPrimaryMinimumAutoRadioButton.AutoSize = true;
+      this.xAxisPrimaryMinimumAutoRadioButton.Location = new System.Drawing.Point(4, 3);
+      this.xAxisPrimaryMinimumAutoRadioButton.Name = "xAxisPrimaryMinimumAutoRadioButton";
+      this.xAxisPrimaryMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisPrimaryMinimumAutoRadioButton.TabIndex = 0;
+      this.xAxisPrimaryMinimumAutoRadioButton.TabStop = true;
+      this.xAxisPrimaryMinimumAutoRadioButton.Text = "Auto";
+      this.xAxisPrimaryMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisPrimaryMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisPrimaryMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryGroupBox
+      // 
+      this.xAxisSecondaryGroupBox.Controls.Add(this.label10);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.xAxisSecondaryTitleTextBox);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.label5);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.label6);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.xAxisSecondaryMaximumPanel);
+      this.xAxisSecondaryGroupBox.Controls.Add(this.xAxisSecondaryMinimumPanel);
+      this.xAxisSecondaryGroupBox.Location = new System.Drawing.Point(6, 119);
+      this.xAxisSecondaryGroupBox.Name = "xAxisSecondaryGroupBox";
+      this.xAxisSecondaryGroupBox.Size = new System.Drawing.Size(316, 106);
+      this.xAxisSecondaryGroupBox.TabIndex = 1;
+      this.xAxisSecondaryGroupBox.TabStop = false;
+      this.xAxisSecondaryGroupBox.Text = "Secondary Axis";
+      // 
+      // label10
+      // 
+      this.label10.AutoSize = true;
+      this.label10.Location = new System.Drawing.Point(4, 26);
+      this.label10.Name = "label10";
+      this.label10.Size = new System.Drawing.Size(30, 13);
+      this.label10.TabIndex = 0;
+      this.label10.Text = "Title:";
+      // 
+      // xAxisSecondaryTitleTextBox
+      // 
+      this.xAxisSecondaryTitleTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.xAxisSecondaryTitleTextBox.Location = new System.Drawing.Point(63, 23);
+      this.xAxisSecondaryTitleTextBox.Name = "xAxisSecondaryTitleTextBox";
+      this.xAxisSecondaryTitleTextBox.Size = new System.Drawing.Size(221, 20);
+      this.xAxisSecondaryTitleTextBox.TabIndex = 1;
+      this.xAxisSecondaryTitleTextBox.Validated += new System.EventHandler(this.xSecondaryTitleTextBox_Validated);
+      // 
+      // label5
+      // 
+      this.label5.AutoSize = true;
+      this.label5.Location = new System.Drawing.Point(4, 77);
+      this.label5.Name = "label5";
+      this.label5.Size = new System.Drawing.Size(54, 13);
+      this.label5.TabIndex = 4;
+      this.label5.Text = "Maximum:";
+      // 
+      // label6
+      // 
+      this.label6.AutoSize = true;
+      this.label6.Location = new System.Drawing.Point(4, 53);
+      this.label6.Name = "label6";
+      this.label6.Size = new System.Drawing.Size(51, 13);
+      this.label6.TabIndex = 2;
+      this.label6.Text = "Minimum:";
+      // 
+      // xAxisSecondaryMaximumPanel
+      // 
+      this.xAxisSecondaryMaximumPanel.Controls.Add(this.xAxisSecondaryMaximumFixedTextBox);
+      this.xAxisSecondaryMaximumPanel.Controls.Add(this.xAxisSecondaryMaximumFixedRadioButton);
+      this.xAxisSecondaryMaximumPanel.Controls.Add(this.xAxisSecondaryMaximumAutoRadioButton);
+      this.xAxisSecondaryMaximumPanel.Location = new System.Drawing.Point(63, 71);
+      this.xAxisSecondaryMaximumPanel.Name = "xAxisSecondaryMaximumPanel";
+      this.xAxisSecondaryMaximumPanel.Size = new System.Drawing.Size(245, 25);
+      this.xAxisSecondaryMaximumPanel.TabIndex = 5;
+      // 
+      // xAxisSecondaryMaximumFixedTextBox
+      // 
+      this.xAxisSecondaryMaximumFixedTextBox.Location = new System.Drawing.Point(126, 2);
+      this.xAxisSecondaryMaximumFixedTextBox.Name = "xAxisSecondaryMaximumFixedTextBox";
+      this.xAxisSecondaryMaximumFixedTextBox.Size = new System.Drawing.Size(95, 20);
+      this.xAxisSecondaryMaximumFixedTextBox.TabIndex = 2;
+      this.xAxisSecondaryMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisSecondaryMaximumFixedTextBox_Validating);
+      // 
+      // xAxisSecondaryMaximumFixedRadioButton
+      // 
+      this.xAxisSecondaryMaximumFixedRadioButton.AutoSize = true;
+      this.xAxisSecondaryMaximumFixedRadioButton.Location = new System.Drawing.Point(70, 4);
+      this.xAxisSecondaryMaximumFixedRadioButton.Name = "xAxisSecondaryMaximumFixedRadioButton";
+      this.xAxisSecondaryMaximumFixedRadioButton.Size = new System.Drawing.Size(50, 17);
+      this.xAxisSecondaryMaximumFixedRadioButton.TabIndex = 1;
+      this.xAxisSecondaryMaximumFixedRadioButton.TabStop = true;
+      this.xAxisSecondaryMaximumFixedRadioButton.Text = "Fixed";
+      this.xAxisSecondaryMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisSecondaryMaximumRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryMaximumAutoRadioButton
+      // 
+      this.xAxisSecondaryMaximumAutoRadioButton.AutoSize = true;
+      this.xAxisSecondaryMaximumAutoRadioButton.Location = new System.Drawing.Point(4, 4);
+      this.xAxisSecondaryMaximumAutoRadioButton.Name = "xAxisSecondaryMaximumAutoRadioButton";
+      this.xAxisSecondaryMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisSecondaryMaximumAutoRadioButton.TabIndex = 0;
+      this.xAxisSecondaryMaximumAutoRadioButton.TabStop = true;
+      this.xAxisSecondaryMaximumAutoRadioButton.Text = "Auto";
+      this.xAxisSecondaryMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisSecondaryMaximumRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryMinimumPanel
+      // 
+      this.xAxisSecondaryMinimumPanel.Controls.Add(this.xAxisSecondaryMinimumFixedTextBox);
+      this.xAxisSecondaryMinimumPanel.Controls.Add(this.xAxisSecondaryMinimumFixedRadioButton);
+      this.xAxisSecondaryMinimumPanel.Controls.Add(this.xAxisSecondaryMinimumAutoRadioButton);
+      this.xAxisSecondaryMinimumPanel.Location = new System.Drawing.Point(63, 47);
+      this.xAxisSecondaryMinimumPanel.Name = "xAxisSecondaryMinimumPanel";
+      this.xAxisSecondaryMinimumPanel.Size = new System.Drawing.Size(245, 25);
+      this.xAxisSecondaryMinimumPanel.TabIndex = 3;
+      // 
+      // xAxisSecondaryMinimumFixedTextBox
+      // 
+      this.xAxisSecondaryMinimumFixedTextBox.Location = new System.Drawing.Point(126, 2);
+      this.xAxisSecondaryMinimumFixedTextBox.Name = "xAxisSecondaryMinimumFixedTextBox";
+      this.xAxisSecondaryMinimumFixedTextBox.Size = new System.Drawing.Size(95, 20);
+      this.xAxisSecondaryMinimumFixedTextBox.TabIndex = 2;
+      this.xAxisSecondaryMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.xAxisSecondaryMinimumFixedTextBox_Validating);
+      // 
+      // xAxisSecondaryMinimumFixedRadioButton
+      // 
+      this.xAxisSecondaryMinimumFixedRadioButton.AutoSize = true;
+      this.xAxisSecondaryMinimumFixedRadioButton.Location = new System.Drawing.Point(70, 3);
+      this.xAxisSecondaryMinimumFixedRadioButton.Name = "xAxisSecondaryMinimumFixedRadioButton";
+      this.xAxisSecondaryMinimumFixedRadioButton.Size = new System.Drawing.Size(50, 17);
+      this.xAxisSecondaryMinimumFixedRadioButton.TabIndex = 1;
+      this.xAxisSecondaryMinimumFixedRadioButton.TabStop = true;
+      this.xAxisSecondaryMinimumFixedRadioButton.Text = "Fixed";
+      this.xAxisSecondaryMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.xAxisSecondaryMinimumRadioButton_CheckedChanged);
+      // 
+      // xAxisSecondaryMinimumAutoRadioButton
+      // 
+      this.xAxisSecondaryMinimumAutoRadioButton.AutoSize = true;
+      this.xAxisSecondaryMinimumAutoRadioButton.Location = new System.Drawing.Point(4, 3);
+      this.xAxisSecondaryMinimumAutoRadioButton.Name = "xAxisSecondaryMinimumAutoRadioButton";
+      this.xAxisSecondaryMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.xAxisSecondaryMinimumAutoRadioButton.TabIndex = 0;
+      this.xAxisSecondaryMinimumAutoRadioButton.TabStop = true;
+      this.xAxisSecondaryMinimumAutoRadioButton.Text = "Auto";
+      this.xAxisSecondaryMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.xAxisSecondaryMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.xAxisSecondaryMinimumRadioButton_CheckedChanged);
+      // 
+      // axisTabControl
+      // 
+      this.axisTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.axisTabControl.Controls.Add(this.mainTabPage);
+      this.axisTabControl.Controls.Add(this.xAxisTabPage);
+      this.axisTabControl.Controls.Add(this.yAxisTabPage);
+      this.axisTabControl.Location = new System.Drawing.Point(0, 0);
+      this.axisTabControl.Name = "axisTabControl";
+      this.axisTabControl.SelectedIndex = 0;
+      this.axisTabControl.Size = new System.Drawing.Size(336, 257);
+      this.axisTabControl.TabIndex = 0;
+      // 
+      // mainTabPage
+      // 
+      this.mainTabPage.Controls.Add(this.axisFontLabel);
+      this.mainTabPage.Controls.Add(this.titleFontLabel);
+      this.mainTabPage.Controls.Add(this.axisFontButton);
+      this.mainTabPage.Controls.Add(this.label3);
+      this.mainTabPage.Controls.Add(this.titleFontButton);
+      this.mainTabPage.Controls.Add(this.label2);
+      this.mainTabPage.Location = new System.Drawing.Point(4, 22);
+      this.mainTabPage.Name = "mainTabPage";
+      this.mainTabPage.Size = new System.Drawing.Size(328, 231);
+      this.mainTabPage.TabIndex = 2;
+      this.mainTabPage.Text = "Main";
+      this.mainTabPage.UseVisualStyleBackColor = true;
+      // 
+      // axisFontLabel
+      // 
+      this.axisFontLabel.AutoSize = true;
+      this.axisFontLabel.Location = new System.Drawing.Point(101, 44);
+      this.axisFontLabel.Name = "axisFontLabel";
+      this.axisFontLabel.Size = new System.Drawing.Size(13, 13);
+      this.axisFontLabel.TabIndex = 2;
+      this.axisFontLabel.Text = "()";
+      // 
+      // titleFontLabel
+      // 
+      this.titleFontLabel.AutoSize = true;
+      this.titleFontLabel.Location = new System.Drawing.Point(101, 15);
+      this.titleFontLabel.Name = "titleFontLabel";
+      this.titleFontLabel.Size = new System.Drawing.Size(13, 13);
+      this.titleFontLabel.TabIndex = 2;
+      this.titleFontLabel.Text = "()";
+      // 
+      // axisFontButton
+      // 
+      this.axisFontButton.Location = new System.Drawing.Point(69, 39);
+      this.axisFontButton.Name = "axisFontButton";
+      this.axisFontButton.Size = new System.Drawing.Size(26, 23);
+      this.axisFontButton.TabIndex = 1;
+      this.axisFontButton.Text = "...";
+      this.axisFontButton.UseVisualStyleBackColor = true;
+      this.axisFontButton.Click += new System.EventHandler(this.axisFontButton_Click);
+      // 
+      // label3
+      // 
+      this.label3.AutoSize = true;
+      this.label3.Location = new System.Drawing.Point(9, 44);
+      this.label3.Name = "label3";
+      this.label3.Size = new System.Drawing.Size(53, 13);
+      this.label3.TabIndex = 0;
+      this.label3.Text = "Axis Font:";
+      // 
+      // titleFontButton
+      // 
+      this.titleFontButton.Location = new System.Drawing.Point(69, 10);
+      this.titleFontButton.Name = "titleFontButton";
+      this.titleFontButton.Size = new System.Drawing.Size(26, 23);
+      this.titleFontButton.TabIndex = 1;
+      this.titleFontButton.Text = "...";
+      this.titleFontButton.UseVisualStyleBackColor = true;
+      this.titleFontButton.Click += new System.EventHandler(this.titleFontButton_Click);
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(9, 15);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(54, 13);
+      this.label2.TabIndex = 0;
+      this.label2.Text = "Title Font:";
+      // 
+      // xAxisTabPage
+      // 
+      this.xAxisTabPage.Controls.Add(this.xAxisSecondaryGroupBox);
+      this.xAxisTabPage.Controls.Add(this.xAxisPrimaryGroupBox);
+      this.xAxisTabPage.Location = new System.Drawing.Point(4, 22);
+      this.xAxisTabPage.Name = "xAxisTabPage";
+      this.xAxisTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.xAxisTabPage.Size = new System.Drawing.Size(328, 231);
+      this.xAxisTabPage.TabIndex = 0;
+      this.xAxisTabPage.Text = "X-Axis";
+      this.xAxisTabPage.UseVisualStyleBackColor = true;
+      // 
+      // yAxisTabPage
+      // 
+      this.yAxisTabPage.Controls.Add(this.yAxisSecondaryGroupBox);
+      this.yAxisTabPage.Controls.Add(this.yAxisPrimaryGroupBox);
+      this.yAxisTabPage.Location = new System.Drawing.Point(4, 22);
+      this.yAxisTabPage.Name = "yAxisTabPage";
+      this.yAxisTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.yAxisTabPage.Size = new System.Drawing.Size(328, 231);
+      this.yAxisTabPage.TabIndex = 1;
+      this.yAxisTabPage.Text = "Y-Axis";
+      this.yAxisTabPage.UseVisualStyleBackColor = true;
+      // 
+      // yAxisSecondaryGroupBox
+      // 
+      this.yAxisSecondaryGroupBox.Controls.Add(this.yAxisSecondaryTitleTextBox);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.label4);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.label13);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.label14);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.yAxisSecondaryMaximumPanel);
+      this.yAxisSecondaryGroupBox.Controls.Add(this.yAxisSecondaryMinimumPanel);
+      this.yAxisSecondaryGroupBox.Location = new System.Drawing.Point(6, 119);
+      this.yAxisSecondaryGroupBox.Name = "yAxisSecondaryGroupBox";
+      this.yAxisSecondaryGroupBox.Size = new System.Drawing.Size(316, 106);
+      this.yAxisSecondaryGroupBox.TabIndex = 1;
+      this.yAxisSecondaryGroupBox.TabStop = false;
+      this.yAxisSecondaryGroupBox.Text = "Secondary Axis";
+      // 
+      // label13
+      // 
+      this.label13.AutoSize = true;
+      this.label13.Location = new System.Drawing.Point(4, 77);
+      this.label13.Name = "label13";
+      this.label13.Size = new System.Drawing.Size(54, 13);
+      this.label13.TabIndex = 4;
+      this.label13.Text = "Maximum:";
+      // 
+      // label14
+      // 
+      this.label14.AutoSize = true;
+      this.label14.Location = new System.Drawing.Point(4, 53);
+      this.label14.Name = "label14";
+      this.label14.Size = new System.Drawing.Size(51, 13);
+      this.label14.TabIndex = 2;
+      this.label14.Text = "Minimum:";
+      // 
+      // yAxisSecondaryMaximumPanel
+      // 
+      this.yAxisSecondaryMaximumPanel.Controls.Add(this.yAxisSecondaryMaximumFixedTextBox);
+      this.yAxisSecondaryMaximumPanel.Controls.Add(this.yAxisSecondaryMaximumFixedRadioButton);
+      this.yAxisSecondaryMaximumPanel.Controls.Add(this.yAxisSecondaryMaximumAutoRadioButton);
+      this.yAxisSecondaryMaximumPanel.Location = new System.Drawing.Point(63, 71);
+      this.yAxisSecondaryMaximumPanel.Name = "yAxisSecondaryMaximumPanel";
+      this.yAxisSecondaryMaximumPanel.Size = new System.Drawing.Size(245, 25);
+      this.yAxisSecondaryMaximumPanel.TabIndex = 5;
+      // 
+      // yAxisSecondaryMaximumFixedTextBox
+      // 
+      this.yAxisSecondaryMaximumFixedTextBox.Location = new System.Drawing.Point(126, 2);
+      this.yAxisSecondaryMaximumFixedTextBox.Name = "yAxisSecondaryMaximumFixedTextBox";
+      this.yAxisSecondaryMaximumFixedTextBox.Size = new System.Drawing.Size(95, 20);
+      this.yAxisSecondaryMaximumFixedTextBox.TabIndex = 2;
+      this.yAxisSecondaryMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisSecondaryMaximumFixedTextBox_Validating);
+      // 
+      // yAxisSecondaryMaximumFixedRadioButton
+      // 
+      this.yAxisSecondaryMaximumFixedRadioButton.AutoSize = true;
+      this.yAxisSecondaryMaximumFixedRadioButton.Location = new System.Drawing.Point(70, 4);
+      this.yAxisSecondaryMaximumFixedRadioButton.Name = "yAxisSecondaryMaximumFixedRadioButton";
+      this.yAxisSecondaryMaximumFixedRadioButton.Size = new System.Drawing.Size(50, 17);
+      this.yAxisSecondaryMaximumFixedRadioButton.TabIndex = 1;
+      this.yAxisSecondaryMaximumFixedRadioButton.TabStop = true;
+      this.yAxisSecondaryMaximumFixedRadioButton.Text = "Fixed";
+      this.yAxisSecondaryMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisSecondaryMaximumRadioButton_CheckedChanged);
+      // 
+      // yAxisSecondaryMaximumAutoRadioButton
+      // 
+      this.yAxisSecondaryMaximumAutoRadioButton.AutoSize = true;
+      this.yAxisSecondaryMaximumAutoRadioButton.Location = new System.Drawing.Point(4, 4);
+      this.yAxisSecondaryMaximumAutoRadioButton.Name = "yAxisSecondaryMaximumAutoRadioButton";
+      this.yAxisSecondaryMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisSecondaryMaximumAutoRadioButton.TabIndex = 0;
+      this.yAxisSecondaryMaximumAutoRadioButton.TabStop = true;
+      this.yAxisSecondaryMaximumAutoRadioButton.Text = "Auto";
+      this.yAxisSecondaryMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisSecondaryMaximumRadioButton_CheckedChanged);
+      // 
+      // yAxisSecondaryMinimumPanel
+      // 
+      this.yAxisSecondaryMinimumPanel.Controls.Add(this.yAxisSecondaryMinimumFixedTextBox);
+      this.yAxisSecondaryMinimumPanel.Controls.Add(this.yAxisSecondaryMinimumFixedRadioButton);
+      this.yAxisSecondaryMinimumPanel.Controls.Add(this.yAxisSecondaryMinimumAutoRadioButton);
+      this.yAxisSecondaryMinimumPanel.Location = new System.Drawing.Point(63, 47);
+      this.yAxisSecondaryMinimumPanel.Name = "yAxisSecondaryMinimumPanel";
+      this.yAxisSecondaryMinimumPanel.Size = new System.Drawing.Size(245, 25);
+      this.yAxisSecondaryMinimumPanel.TabIndex = 3;
+      // 
+      // yAxisSecondaryMinimumFixedTextBox
+      // 
+      this.yAxisSecondaryMinimumFixedTextBox.Location = new System.Drawing.Point(126, 2);
+      this.yAxisSecondaryMinimumFixedTextBox.Name = "yAxisSecondaryMinimumFixedTextBox";
+      this.yAxisSecondaryMinimumFixedTextBox.Size = new System.Drawing.Size(95, 20);
+      this.yAxisSecondaryMinimumFixedTextBox.TabIndex = 2;
+      this.yAxisSecondaryMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisSecondaryMinimumFixedTextBox_Validating);
+      // 
+      // yAxisSecondaryMinimumFixedRadioButton
+      // 
+      this.yAxisSecondaryMinimumFixedRadioButton.AutoSize = true;
+      this.yAxisSecondaryMinimumFixedRadioButton.Location = new System.Drawing.Point(70, 3);
+      this.yAxisSecondaryMinimumFixedRadioButton.Name = "yAxisSecondaryMinimumFixedRadioButton";
+      this.yAxisSecondaryMinimumFixedRadioButton.Size = new System.Drawing.Size(50, 17);
+      this.yAxisSecondaryMinimumFixedRadioButton.TabIndex = 1;
+      this.yAxisSecondaryMinimumFixedRadioButton.TabStop = true;
+      this.yAxisSecondaryMinimumFixedRadioButton.Text = "Fixed";
+      this.yAxisSecondaryMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisSecondaryMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisSecondaryMinimumAutoRadioButton
+      // 
+      this.yAxisSecondaryMinimumAutoRadioButton.AutoSize = true;
+      this.yAxisSecondaryMinimumAutoRadioButton.Location = new System.Drawing.Point(4, 3);
+      this.yAxisSecondaryMinimumAutoRadioButton.Name = "yAxisSecondaryMinimumAutoRadioButton";
+      this.yAxisSecondaryMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisSecondaryMinimumAutoRadioButton.TabIndex = 0;
+      this.yAxisSecondaryMinimumAutoRadioButton.TabStop = true;
+      this.yAxisSecondaryMinimumAutoRadioButton.Text = "Auto";
+      this.yAxisSecondaryMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisSecondaryMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisSecondaryMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryGroupBox
+      // 
+      this.yAxisPrimaryGroupBox.Controls.Add(this.label7);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.yAxisPrimaryTitleTextBox);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.label8);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.label1);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.yAxisPrimaryMaximumPanel);
+      this.yAxisPrimaryGroupBox.Controls.Add(this.yAxisPrimaryMinimumPanel);
+      this.yAxisPrimaryGroupBox.Location = new System.Drawing.Point(6, 6);
+      this.yAxisPrimaryGroupBox.Name = "yAxisPrimaryGroupBox";
+      this.yAxisPrimaryGroupBox.Size = new System.Drawing.Size(316, 107);
+      this.yAxisPrimaryGroupBox.TabIndex = 0;
+      this.yAxisPrimaryGroupBox.TabStop = false;
+      this.yAxisPrimaryGroupBox.Text = "Primary Axis";
+      // 
+      // label7
+      // 
+      this.label7.AutoSize = true;
+      this.label7.Location = new System.Drawing.Point(4, 77);
+      this.label7.Name = "label7";
+      this.label7.Size = new System.Drawing.Size(54, 13);
+      this.label7.TabIndex = 4;
+      this.label7.Text = "Maximum:";
+      // 
+      // label8
+      // 
+      this.label8.AutoSize = true;
+      this.label8.Location = new System.Drawing.Point(4, 53);
+      this.label8.Name = "label8";
+      this.label8.Size = new System.Drawing.Size(51, 13);
+      this.label8.TabIndex = 2;
+      this.label8.Text = "Minimum:";
+      // 
+      // yAxisPrimaryMaximumPanel
+      // 
+      this.yAxisPrimaryMaximumPanel.Controls.Add(this.yAxisPrimaryMaximumFixedTextBox);
+      this.yAxisPrimaryMaximumPanel.Controls.Add(this.yAxisPrimaryMaximumFixedRadioButton);
+      this.yAxisPrimaryMaximumPanel.Controls.Add(this.yAxisPrimaryMaximumAutoRadioButton);
+      this.yAxisPrimaryMaximumPanel.Location = new System.Drawing.Point(63, 71);
+      this.yAxisPrimaryMaximumPanel.Name = "yAxisPrimaryMaximumPanel";
+      this.yAxisPrimaryMaximumPanel.Size = new System.Drawing.Size(245, 25);
+      this.yAxisPrimaryMaximumPanel.TabIndex = 5;
+      // 
+      // yAxisPrimaryMaximumFixedTextBox
+      // 
+      this.yAxisPrimaryMaximumFixedTextBox.Location = new System.Drawing.Point(126, 2);
+      this.yAxisPrimaryMaximumFixedTextBox.Name = "yAxisPrimaryMaximumFixedTextBox";
+      this.yAxisPrimaryMaximumFixedTextBox.Size = new System.Drawing.Size(95, 20);
+      this.yAxisPrimaryMaximumFixedTextBox.TabIndex = 2;
+      this.yAxisPrimaryMaximumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisPrimaryMaximumFixedTextBox_Validating);
+      // 
+      // yAxisPrimaryMaximumFixedRadioButton
+      // 
+      this.yAxisPrimaryMaximumFixedRadioButton.AutoSize = true;
+      this.yAxisPrimaryMaximumFixedRadioButton.Location = new System.Drawing.Point(70, 4);
+      this.yAxisPrimaryMaximumFixedRadioButton.Name = "yAxisPrimaryMaximumFixedRadioButton";
+      this.yAxisPrimaryMaximumFixedRadioButton.Size = new System.Drawing.Size(50, 17);
+      this.yAxisPrimaryMaximumFixedRadioButton.TabIndex = 1;
+      this.yAxisPrimaryMaximumFixedRadioButton.TabStop = true;
+      this.yAxisPrimaryMaximumFixedRadioButton.Text = "Fixed";
+      this.yAxisPrimaryMaximumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryMaximumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisPrimaryMaximumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMaximumAutoRadioButton
+      // 
+      this.yAxisPrimaryMaximumAutoRadioButton.AutoSize = true;
+      this.yAxisPrimaryMaximumAutoRadioButton.Location = new System.Drawing.Point(4, 4);
+      this.yAxisPrimaryMaximumAutoRadioButton.Name = "yAxisPrimaryMaximumAutoRadioButton";
+      this.yAxisPrimaryMaximumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisPrimaryMaximumAutoRadioButton.TabIndex = 0;
+      this.yAxisPrimaryMaximumAutoRadioButton.TabStop = true;
+      this.yAxisPrimaryMaximumAutoRadioButton.Text = "Auto";
+      this.yAxisPrimaryMaximumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryMaximumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisPrimaryMaximumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMinimumPanel
+      // 
+      this.yAxisPrimaryMinimumPanel.Controls.Add(this.yAxisPrimaryMinimumFixedTextBox);
+      this.yAxisPrimaryMinimumPanel.Controls.Add(this.yAxisPrimaryMinimumFixedRadioButton);
+      this.yAxisPrimaryMinimumPanel.Controls.Add(this.yAxisPrimaryMinimumAutoRadioButton);
+      this.yAxisPrimaryMinimumPanel.Location = new System.Drawing.Point(63, 47);
+      this.yAxisPrimaryMinimumPanel.Name = "yAxisPrimaryMinimumPanel";
+      this.yAxisPrimaryMinimumPanel.Size = new System.Drawing.Size(245, 25);
+      this.yAxisPrimaryMinimumPanel.TabIndex = 3;
+      // 
+      // yAxisPrimaryMinimumFixedTextBox
+      // 
+      this.yAxisPrimaryMinimumFixedTextBox.Location = new System.Drawing.Point(126, 2);
+      this.yAxisPrimaryMinimumFixedTextBox.Name = "yAxisPrimaryMinimumFixedTextBox";
+      this.yAxisPrimaryMinimumFixedTextBox.Size = new System.Drawing.Size(95, 20);
+      this.yAxisPrimaryMinimumFixedTextBox.TabIndex = 2;
+      this.yAxisPrimaryMinimumFixedTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.yAxisPrimaryMinimumFixedTextBox_Validating);
+      // 
+      // yAxisPrimaryMinimumFixedRadioButton
+      // 
+      this.yAxisPrimaryMinimumFixedRadioButton.AutoSize = true;
+      this.yAxisPrimaryMinimumFixedRadioButton.Location = new System.Drawing.Point(70, 3);
+      this.yAxisPrimaryMinimumFixedRadioButton.Name = "yAxisPrimaryMinimumFixedRadioButton";
+      this.yAxisPrimaryMinimumFixedRadioButton.Size = new System.Drawing.Size(50, 17);
+      this.yAxisPrimaryMinimumFixedRadioButton.TabIndex = 1;
+      this.yAxisPrimaryMinimumFixedRadioButton.TabStop = true;
+      this.yAxisPrimaryMinimumFixedRadioButton.Text = "Fixed";
+      this.yAxisPrimaryMinimumFixedRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryMinimumFixedRadioButton.CheckedChanged += new System.EventHandler(this.yAxisPrimaryMinimumRadioButton_CheckedChanged);
+      // 
+      // yAxisPrimaryMinimumAutoRadioButton
+      // 
+      this.yAxisPrimaryMinimumAutoRadioButton.AutoSize = true;
+      this.yAxisPrimaryMinimumAutoRadioButton.Location = new System.Drawing.Point(4, 3);
+      this.yAxisPrimaryMinimumAutoRadioButton.Name = "yAxisPrimaryMinimumAutoRadioButton";
+      this.yAxisPrimaryMinimumAutoRadioButton.Size = new System.Drawing.Size(47, 17);
+      this.yAxisPrimaryMinimumAutoRadioButton.TabIndex = 0;
+      this.yAxisPrimaryMinimumAutoRadioButton.TabStop = true;
+      this.yAxisPrimaryMinimumAutoRadioButton.Text = "Auto";
+      this.yAxisPrimaryMinimumAutoRadioButton.UseVisualStyleBackColor = true;
+      this.yAxisPrimaryMinimumAutoRadioButton.CheckedChanged += new System.EventHandler(this.yAxisPrimaryMinimumRadioButton_CheckedChanged);
+      // 
+      // errorProvider
+      // 
+      this.errorProvider.ContainerControl = this;
+      // 
+      // titleFontDialog
+      // 
+      this.titleFontDialog.FontMustExist = true;
+      this.titleFontDialog.ShowColor = true;
+      // 
+      // DataTableVisualPropertiesControl
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.axisTabControl);
+      this.Name = "DataTableVisualPropertiesControl";
+      this.Size = new System.Drawing.Size(336, 257);
+      this.xAxisPrimaryGroupBox.ResumeLayout(false);
+      this.xAxisPrimaryGroupBox.PerformLayout();
+      this.xAxisPrimaryMaximumPanel.ResumeLayout(false);
+      this.xAxisPrimaryMaximumPanel.PerformLayout();
+      this.xAxisPrimaryMinimumPanel.ResumeLayout(false);
+      this.xAxisPrimaryMinimumPanel.PerformLayout();
+      this.xAxisSecondaryGroupBox.ResumeLayout(false);
+      this.xAxisSecondaryGroupBox.PerformLayout();
+      this.xAxisSecondaryMaximumPanel.ResumeLayout(false);
+      this.xAxisSecondaryMaximumPanel.PerformLayout();
+      this.xAxisSecondaryMinimumPanel.ResumeLayout(false);
+      this.xAxisSecondaryMinimumPanel.PerformLayout();
+      this.axisTabControl.ResumeLayout(false);
+      this.mainTabPage.ResumeLayout(false);
+      this.mainTabPage.PerformLayout();
+      this.xAxisTabPage.ResumeLayout(false);
+      this.yAxisTabPage.ResumeLayout(false);
+      this.yAxisSecondaryGroupBox.ResumeLayout(false);
+      this.yAxisSecondaryGroupBox.PerformLayout();
+      this.yAxisSecondaryMaximumPanel.ResumeLayout(false);
+      this.yAxisSecondaryMaximumPanel.PerformLayout();
+      this.yAxisSecondaryMinimumPanel.ResumeLayout(false);
+      this.yAxisSecondaryMinimumPanel.PerformLayout();
+      this.yAxisPrimaryGroupBox.ResumeLayout(false);
+      this.yAxisPrimaryGroupBox.PerformLayout();
+      this.yAxisPrimaryMaximumPanel.ResumeLayout(false);
+      this.yAxisPrimaryMaximumPanel.PerformLayout();
+      this.yAxisPrimaryMinimumPanel.ResumeLayout(false);
+      this.yAxisPrimaryMinimumPanel.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.TextBox yAxisPrimaryTitleTextBox;
+    private System.Windows.Forms.TextBox yAxisSecondaryTitleTextBox;
+    private System.Windows.Forms.Label label4;
+    private System.Windows.Forms.GroupBox xAxisPrimaryGroupBox;
+    private System.Windows.Forms.Label label12;
+    private System.Windows.Forms.Label label9;
+    private System.Windows.Forms.TextBox xAxisPrimaryTitleTextBox;
+    private System.Windows.Forms.Label label11;
+    private System.Windows.Forms.Panel xAxisPrimaryMaximumPanel;
+    private System.Windows.Forms.TextBox xAxisPrimaryMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisPrimaryMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisPrimaryMaximumAutoRadioButton;
+    private System.Windows.Forms.Panel xAxisPrimaryMinimumPanel;
+    private System.Windows.Forms.TextBox xAxisPrimaryMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisPrimaryMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisPrimaryMinimumAutoRadioButton;
+    private System.Windows.Forms.GroupBox xAxisSecondaryGroupBox;
+    private System.Windows.Forms.Label label10;
+    private System.Windows.Forms.TextBox xAxisSecondaryTitleTextBox;
+    private System.Windows.Forms.Label label5;
+    private System.Windows.Forms.Label label6;
+    private System.Windows.Forms.Panel xAxisSecondaryMaximumPanel;
+    private System.Windows.Forms.TextBox xAxisSecondaryMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisSecondaryMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisSecondaryMaximumAutoRadioButton;
+    private System.Windows.Forms.Panel xAxisSecondaryMinimumPanel;
+    private System.Windows.Forms.TextBox xAxisSecondaryMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton xAxisSecondaryMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton xAxisSecondaryMinimumAutoRadioButton;
+    private System.Windows.Forms.TabControl axisTabControl;
+    private System.Windows.Forms.TabPage xAxisTabPage;
+    private System.Windows.Forms.TabPage yAxisTabPage;
+    private System.Windows.Forms.GroupBox yAxisSecondaryGroupBox;
+    private System.Windows.Forms.Label label13;
+    private System.Windows.Forms.Label label14;
+    private System.Windows.Forms.Panel yAxisSecondaryMaximumPanel;
+    private System.Windows.Forms.TextBox yAxisSecondaryMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisSecondaryMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisSecondaryMaximumAutoRadioButton;
+    private System.Windows.Forms.Panel yAxisSecondaryMinimumPanel;
+    private System.Windows.Forms.TextBox yAxisSecondaryMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisSecondaryMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisSecondaryMinimumAutoRadioButton;
+    private System.Windows.Forms.GroupBox yAxisPrimaryGroupBox;
+    private System.Windows.Forms.Label label7;
+    private System.Windows.Forms.Label label8;
+    private System.Windows.Forms.Panel yAxisPrimaryMaximumPanel;
+    private System.Windows.Forms.TextBox yAxisPrimaryMaximumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisPrimaryMaximumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisPrimaryMaximumAutoRadioButton;
+    private System.Windows.Forms.Panel yAxisPrimaryMinimumPanel;
+    private System.Windows.Forms.TextBox yAxisPrimaryMinimumFixedTextBox;
+    private System.Windows.Forms.RadioButton yAxisPrimaryMinimumFixedRadioButton;
+    private System.Windows.Forms.RadioButton yAxisPrimaryMinimumAutoRadioButton;
+    private System.Windows.Forms.ErrorProvider errorProvider;
+    private System.Windows.Forms.TabPage mainTabPage;
+    private System.Windows.Forms.FontDialog titleFontDialog;
+    private System.Windows.Forms.Button titleFontButton;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.Button axisFontButton;
+    private System.Windows.Forms.Label label3;
+    private System.Windows.Forms.Label axisFontLabel;
+    private System.Windows.Forms.Label titleFontLabel;
+    private System.Windows.Forms.FontDialog axisFontDialog;
+  }
+}
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.cs	(revision 6342)
@@ -0,0 +1,424 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Drawing;
+using System.Windows.Forms;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("DataRow Visual Properties")]
+  public partial class DataTableVisualPropertiesControl : UserControl {
+    protected bool SuppressEvents { get; set; }
+
+    private DataTableVisualProperties content;
+    public DataTableVisualProperties Content {
+      get { return content; }
+      set {
+        bool changed = (value != content);
+        content = value;
+        if (changed) OnContentChanged();
+      }
+    }
+
+    public DataTableVisualPropertiesControl() {
+      InitializeComponent();
+    }
+
+    protected virtual void OnContentChanged() {
+      SuppressEvents = true;
+      try {
+        if (Content == null) {
+          titleFontLabel.Text = "(  )";
+          axisFontLabel.Text = "(  )";
+
+          xAxisPrimaryTitleTextBox.Text = string.Empty;
+          xAxisPrimaryMinimumAutoRadioButton.Checked = false;
+          xAxisPrimaryMinimumFixedRadioButton.Checked = false;
+          xAxisPrimaryMinimumFixedTextBox.Text = string.Empty;
+          xAxisPrimaryMaximumAutoRadioButton.Checked = false;
+          xAxisPrimaryMaximumFixedRadioButton.Checked = false;
+          xAxisPrimaryMaximumFixedTextBox.Text = string.Empty;
+          xAxisSecondaryTitleTextBox.Text = string.Empty;
+          xAxisSecondaryMinimumAutoRadioButton.Checked = false;
+          xAxisSecondaryMinimumFixedRadioButton.Checked = false;
+          xAxisSecondaryMinimumFixedTextBox.Text = string.Empty;
+          xAxisSecondaryMaximumAutoRadioButton.Checked = false;
+          xAxisSecondaryMaximumFixedRadioButton.Checked = false;
+          xAxisSecondaryMaximumFixedTextBox.Text = string.Empty;
+
+          yAxisPrimaryTitleTextBox.Text = string.Empty;
+          yAxisPrimaryMinimumAutoRadioButton.Checked = false;
+          yAxisPrimaryMinimumFixedRadioButton.Checked = false;
+          yAxisPrimaryMinimumFixedTextBox.Text = string.Empty;
+          yAxisPrimaryMaximumAutoRadioButton.Checked = false;
+          yAxisPrimaryMaximumFixedRadioButton.Checked = false;
+          yAxisPrimaryMaximumFixedTextBox.Text = string.Empty;
+          yAxisSecondaryTitleTextBox.Text = string.Empty;
+          yAxisSecondaryMinimumAutoRadioButton.Checked = false;
+          yAxisSecondaryMinimumFixedRadioButton.Checked = false;
+          yAxisSecondaryMinimumFixedTextBox.Text = string.Empty;
+          yAxisSecondaryMaximumAutoRadioButton.Checked = false;
+          yAxisSecondaryMaximumFixedRadioButton.Checked = false;
+          yAxisSecondaryMaximumFixedTextBox.Text = string.Empty;
+        } else {
+          titleFontLabel.Text = "( " + FormatFont(Content.TitleFont) + " )";
+          axisFontLabel.Text = "( " + FormatFont(Content.AxisTitleFont) + " )";
+
+          xAxisPrimaryTitleTextBox.Text = Content.XAxisTitle;
+          xAxisPrimaryMinimumAutoRadioButton.Checked = Content.XAxisMinimumAuto;
+          xAxisPrimaryMinimumFixedRadioButton.Checked = !Content.XAxisMinimumAuto;
+          xAxisPrimaryMinimumFixedTextBox.Text = Content.XAxisMinimumFixedValue.ToString();
+          xAxisPrimaryMaximumAutoRadioButton.Checked = Content.XAxisMaximumAuto;
+          xAxisPrimaryMaximumFixedRadioButton.Checked = !Content.XAxisMaximumAuto;
+          xAxisPrimaryMaximumFixedTextBox.Text = Content.XAxisMaximumFixedValue.ToString();
+          xAxisSecondaryTitleTextBox.Text = Content.SecondXAxisTitle;
+          xAxisSecondaryMinimumAutoRadioButton.Checked = Content.SecondXAxisMinimumAuto;
+          xAxisSecondaryMinimumFixedRadioButton.Checked = !Content.SecondXAxisMinimumAuto;
+          xAxisSecondaryMinimumFixedTextBox.Text = Content.SecondXAxisMinimumFixedValue.ToString();
+          xAxisSecondaryMaximumAutoRadioButton.Checked = Content.SecondXAxisMaximumAuto;
+          xAxisSecondaryMaximumFixedRadioButton.Checked = !Content.SecondXAxisMaximumAuto;
+          xAxisSecondaryMaximumFixedTextBox.Text = Content.SecondXAxisMaximumFixedValue.ToString();
+
+          yAxisPrimaryTitleTextBox.Text = Content.YAxisTitle;
+          yAxisPrimaryMinimumAutoRadioButton.Checked = Content.YAxisMinimumAuto;
+          yAxisPrimaryMinimumFixedRadioButton.Checked = !Content.YAxisMinimumAuto;
+          yAxisPrimaryMinimumFixedTextBox.Text = Content.YAxisMinimumFixedValue.ToString();
+          yAxisPrimaryMaximumAutoRadioButton.Checked = Content.YAxisMaximumAuto;
+          yAxisPrimaryMaximumFixedRadioButton.Checked = !Content.YAxisMaximumAuto;
+          yAxisPrimaryMaximumFixedTextBox.Text = Content.YAxisMaximumFixedValue.ToString();
+          yAxisSecondaryTitleTextBox.Text = Content.SecondYAxisTitle;
+          yAxisSecondaryMinimumAutoRadioButton.Checked = Content.SecondYAxisMinimumAuto;
+          yAxisSecondaryMinimumFixedRadioButton.Checked = !Content.SecondYAxisMinimumAuto;
+          yAxisSecondaryMinimumFixedTextBox.Text = Content.SecondYAxisMinimumFixedValue.ToString();
+          yAxisSecondaryMaximumAutoRadioButton.Checked = Content.SecondYAxisMaximumAuto;
+          yAxisSecondaryMaximumFixedRadioButton.Checked = !Content.SecondYAxisMaximumAuto;
+          yAxisSecondaryMaximumFixedTextBox.Text = Content.SecondYAxisMaximumFixedValue.ToString();
+        }
+      } finally { SuppressEvents = false; }
+      SetEnabledStateOfControls();
+    }
+
+    protected virtual void SetEnabledStateOfControls() {
+      axisTabControl.Enabled = Content != null;
+      xAxisPrimaryMinimumFixedTextBox.Enabled = xAxisPrimaryMinimumFixedRadioButton.Checked;
+      xAxisPrimaryMaximumFixedTextBox.Enabled = xAxisPrimaryMaximumFixedRadioButton.Checked;
+      xAxisSecondaryMinimumFixedTextBox.Enabled = xAxisSecondaryMinimumFixedRadioButton.Checked;
+      xAxisSecondaryMaximumFixedTextBox.Enabled = xAxisSecondaryMaximumFixedRadioButton.Checked;
+
+      yAxisPrimaryMinimumFixedTextBox.Enabled = yAxisPrimaryMinimumFixedRadioButton.Checked;
+      yAxisPrimaryMaximumFixedTextBox.Enabled = yAxisPrimaryMaximumFixedRadioButton.Checked;
+      yAxisSecondaryMinimumFixedTextBox.Enabled = yAxisSecondaryMinimumFixedRadioButton.Checked;
+      yAxisSecondaryMaximumFixedTextBox.Enabled = yAxisSecondaryMaximumFixedRadioButton.Checked;
+    }
+
+    #region Event Handlers
+    private void yPrimaryTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.YAxisTitle = yAxisPrimaryTitleTextBox.Text;
+      }
+    }
+
+    private void ySecondaryTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.SecondYAxisTitle = yAxisSecondaryTitleTextBox.Text;
+      }
+    }
+
+    private void xPrimaryTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.XAxisTitle = xAxisPrimaryTitleTextBox.Text;
+      }
+    }
+
+    private void xSecondaryTitleTextBox_Validated(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        Content.SecondXAxisTitle = xAxisSecondaryTitleTextBox.Text;
+      }
+    }
+
+    private void xAxisPrimaryMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.XAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.XAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisPrimaryMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.XAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.XAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisSecondaryMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.SecondXAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.SecondXAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisSecondaryMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.SecondXAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.SecondXAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisPrimaryMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.YAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.YAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisPrimaryMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.YAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.YAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisSecondaryMinimumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val >= Content.SecondYAxisMaximumFixedValue) {
+            errorProvider.SetError(tb, "Number must be smaller than maximum.");
+            e.Cancel = true;
+          } else {
+            Content.SecondYAxisMinimumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void yAxisSecondaryMaximumFixedTextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        TextBox tb = (TextBox)sender;
+        double val;
+        if (double.TryParse(tb.Text, out val)) {
+          if (val <= Content.SecondYAxisMinimumFixedValue) {
+            errorProvider.SetError(tb, "Number must be greater than minimum.");
+            e.Cancel = true;
+          } else {
+            Content.SecondYAxisMaximumFixedValue = val;
+            errorProvider.SetError(tb, string.Empty);
+          }
+        } else {
+          errorProvider.SetError(tb, "Not a valid number.");
+          e.Cancel = true;
+        }
+      }
+    }
+
+    private void xAxisPrimaryMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.XAxisMinimumAuto = xAxisPrimaryMinimumAutoRadioButton.Checked;
+          if (Content.XAxisMinimumAuto) xAxisPrimaryMinimumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void xAxisPrimaryMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.XAxisMaximumAuto = xAxisPrimaryMaximumAutoRadioButton.Checked;
+          if (Content.XAxisMaximumAuto) xAxisPrimaryMaximumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void xAxisSecondaryMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondXAxisMinimumAuto = xAxisSecondaryMinimumAutoRadioButton.Checked;
+          if (Content.SecondXAxisMinimumAuto) xAxisSecondaryMinimumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void xAxisSecondaryMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondXAxisMaximumAuto = xAxisSecondaryMaximumAutoRadioButton.Checked;
+          if (Content.SecondXAxisMaximumAuto) xAxisSecondaryMaximumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisPrimaryMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.YAxisMinimumAuto = yAxisPrimaryMinimumAutoRadioButton.Checked;
+          if (Content.YAxisMinimumAuto) yAxisPrimaryMinimumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisPrimaryMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.YAxisMaximumAuto = yAxisPrimaryMaximumAutoRadioButton.Checked;
+          if (Content.YAxisMaximumAuto) yAxisPrimaryMaximumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisSecondaryMinimumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondYAxisMinimumAuto = yAxisSecondaryMinimumAutoRadioButton.Checked;
+          if (Content.SecondYAxisMinimumAuto) yAxisSecondaryMinimumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void yAxisSecondaryMaximumRadioButton_CheckedChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents && Content != null) {
+        SuppressEvents = true;
+        try {
+          Content.SecondYAxisMaximumAuto = yAxisSecondaryMaximumAutoRadioButton.Checked;
+          if (Content.SecondYAxisMaximumAuto) yAxisSecondaryMaximumFixedTextBox.Text = double.NaN.ToString();
+        } finally { SuppressEvents = false; }
+        SetEnabledStateOfControls();
+      }
+    }
+
+    private void titleFontButton_Click(object sender, System.EventArgs e) {
+      titleFontDialog.Font = Content.TitleFont;
+      titleFontDialog.Color = Content.TitleColor;
+      if (titleFontDialog.ShowDialog() == DialogResult.OK) {
+        Content.TitleFont = titleFontDialog.Font;
+        Content.TitleColor = titleFontDialog.Color;
+        titleFontLabel.Text = "( " + FormatFont(Content.TitleFont) + " )";
+      }
+    }
+
+    private void axisFontButton_Click(object sender, System.EventArgs e) {
+      axisFontDialog.Font = Content.AxisTitleFont;
+      axisFontDialog.Color = Content.AxisTitleColor;
+      if (axisFontDialog.ShowDialog() == DialogResult.OK) {
+        Content.AxisTitleFont = axisFontDialog.Font;
+        Content.AxisTitleColor = axisFontDialog.Color;
+        axisFontLabel.Text = "( " + FormatFont(Content.AxisTitleFont) + " )";
+      }
+    }
+    #endregion
+
+    private string FormatFont(Font f) {
+      if (f == null) return string.Empty;
+      else return f.Name + ", " + f.SizeInPoints.ToString() + "pt, " + f.Style.ToString();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.resx
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.resx	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesControl.resx	(revision 6342)
@@ -0,0 +1,129 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="titleFontDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>140, 17</value>
+  </metadata>
+  <metadata name="axisFontDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>272, 17</value>
+  </metadata>
+</root>
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.Designer.cs	(revision 6342)
@@ -0,0 +1,240 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Analysis.Views {
+  partial class DataTableVisualPropertiesDialog {
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Windows Form Designer generated code
+
+    /// <summary>
+    /// Required method for Designer support - do not modify
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.okButton = new System.Windows.Forms.Button();
+      this.cancelButton = new System.Windows.Forms.Button();
+      this.tabControl = new System.Windows.Forms.TabControl();
+      this.seriesTabPage = new System.Windows.Forms.TabPage();
+      this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.downButton = new System.Windows.Forms.Button();
+      this.upButton = new System.Windows.Forms.Button();
+      this.seriesListView = new System.Windows.Forms.ListView();
+      this.dataRowVisualPropertiesControl = new HeuristicLab.Analysis.Views.DataRowVisualPropertiesControl();
+      this.chartTabPage = new System.Windows.Forms.TabPage();
+      this.dataTableVisualPropertiesControl = new HeuristicLab.Analysis.Views.DataTableVisualPropertiesControl();
+      this.tabControl.SuspendLayout();
+      this.seriesTabPage.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
+      this.splitContainer.Panel1.SuspendLayout();
+      this.splitContainer.Panel2.SuspendLayout();
+      this.splitContainer.SuspendLayout();
+      this.chartTabPage.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // okButton
+      // 
+      this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.okButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      this.okButton.Location = new System.Drawing.Point(307, 357);
+      this.okButton.Name = "okButton";
+      this.okButton.Size = new System.Drawing.Size(75, 23);
+      this.okButton.TabIndex = 0;
+      this.okButton.Text = "Ok";
+      this.okButton.UseVisualStyleBackColor = true;
+      this.okButton.Click += new System.EventHandler(this.okButton_Click);
+      // 
+      // cancelButton
+      // 
+      this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+      this.cancelButton.Location = new System.Drawing.Point(388, 357);
+      this.cancelButton.Name = "cancelButton";
+      this.cancelButton.Size = new System.Drawing.Size(75, 23);
+      this.cancelButton.TabIndex = 1;
+      this.cancelButton.Text = "Cancel";
+      this.cancelButton.UseVisualStyleBackColor = true;
+      this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
+      // 
+      // tabControl
+      // 
+      this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.tabControl.Controls.Add(this.seriesTabPage);
+      this.tabControl.Controls.Add(this.chartTabPage);
+      this.tabControl.Location = new System.Drawing.Point(0, 0);
+      this.tabControl.Name = "tabControl";
+      this.tabControl.SelectedIndex = 0;
+      this.tabControl.Size = new System.Drawing.Size(474, 350);
+      this.tabControl.TabIndex = 2;
+      // 
+      // seriesTabPage
+      // 
+      this.seriesTabPage.Controls.Add(this.splitContainer);
+      this.seriesTabPage.Location = new System.Drawing.Point(4, 22);
+      this.seriesTabPage.Name = "seriesTabPage";
+      this.seriesTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.seriesTabPage.Size = new System.Drawing.Size(466, 324);
+      this.seriesTabPage.TabIndex = 0;
+      this.seriesTabPage.Text = "Series";
+      this.seriesTabPage.UseVisualStyleBackColor = true;
+      // 
+      // splitContainer
+      // 
+      this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+      this.splitContainer.Location = new System.Drawing.Point(3, 3);
+      this.splitContainer.Name = "splitContainer";
+      // 
+      // splitContainer.Panel1
+      // 
+      this.splitContainer.Panel1.Controls.Add(this.downButton);
+      this.splitContainer.Panel1.Controls.Add(this.upButton);
+      this.splitContainer.Panel1.Controls.Add(this.seriesListView);
+      this.splitContainer.Panel1MinSize = 20;
+      // 
+      // splitContainer.Panel2
+      // 
+      this.splitContainer.Panel2.Controls.Add(this.dataRowVisualPropertiesControl);
+      this.splitContainer.Panel2MinSize = 50;
+      this.splitContainer.Size = new System.Drawing.Size(460, 318);
+      this.splitContainer.SplitterDistance = 125;
+      this.splitContainer.TabIndex = 0;
+      // 
+      // downButton
+      // 
+      this.downButton.Location = new System.Drawing.Point(27, 3);
+      this.downButton.Name = "downButton";
+      this.downButton.Size = new System.Drawing.Size(26, 23);
+      this.downButton.TabIndex = 1;
+      this.downButton.Text = "Down";
+      this.downButton.UseVisualStyleBackColor = true;
+      this.downButton.Click += new System.EventHandler(this.downButton_Click);
+      // 
+      // upButton
+      // 
+      this.upButton.Location = new System.Drawing.Point(-1, 3);
+      this.upButton.Name = "upButton";
+      this.upButton.Size = new System.Drawing.Size(26, 23);
+      this.upButton.TabIndex = 1;
+      this.upButton.Text = "Up";
+      this.upButton.UseVisualStyleBackColor = true;
+      this.upButton.Click += new System.EventHandler(this.upButton_Click);
+      // 
+      // seriesListView
+      // 
+      this.seriesListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.seriesListView.HideSelection = false;
+      this.seriesListView.Location = new System.Drawing.Point(0, 28);
+      this.seriesListView.MultiSelect = false;
+      this.seriesListView.Name = "seriesListView";
+      this.seriesListView.ShowGroups = false;
+      this.seriesListView.Size = new System.Drawing.Size(125, 289);
+      this.seriesListView.TabIndex = 0;
+      this.seriesListView.UseCompatibleStateImageBehavior = false;
+      this.seriesListView.View = System.Windows.Forms.View.SmallIcon;
+      this.seriesListView.SelectedIndexChanged += new System.EventHandler(this.seriesListView_SelectedIndexChanged);
+      // 
+      // dataRowVisualPropertiesControl
+      // 
+      this.dataRowVisualPropertiesControl.Content = null;
+      this.dataRowVisualPropertiesControl.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.dataRowVisualPropertiesControl.Location = new System.Drawing.Point(0, 0);
+      this.dataRowVisualPropertiesControl.Name = "dataRowVisualPropertiesControl";
+      this.dataRowVisualPropertiesControl.Size = new System.Drawing.Size(331, 318);
+      this.dataRowVisualPropertiesControl.TabIndex = 0;
+      // 
+      // chartTabPage
+      // 
+      this.chartTabPage.Controls.Add(this.dataTableVisualPropertiesControl);
+      this.chartTabPage.Location = new System.Drawing.Point(4, 22);
+      this.chartTabPage.Name = "chartTabPage";
+      this.chartTabPage.Padding = new System.Windows.Forms.Padding(3);
+      this.chartTabPage.Size = new System.Drawing.Size(466, 324);
+      this.chartTabPage.TabIndex = 1;
+      this.chartTabPage.Text = "Chart";
+      this.chartTabPage.UseVisualStyleBackColor = true;
+      // 
+      // dataTableVisualPropertiesControl
+      // 
+      this.dataTableVisualPropertiesControl.Content = null;
+      this.dataTableVisualPropertiesControl.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.dataTableVisualPropertiesControl.Location = new System.Drawing.Point(3, 3);
+      this.dataTableVisualPropertiesControl.Name = "dataTableVisualPropertiesControl";
+      this.dataTableVisualPropertiesControl.Size = new System.Drawing.Size(460, 318);
+      this.dataTableVisualPropertiesControl.TabIndex = 0;
+      // 
+      // DataTableVisualPropertiesDialog
+      // 
+      this.AcceptButton = this.okButton;
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.CancelButton = this.cancelButton;
+      this.ClientSize = new System.Drawing.Size(475, 392);
+      this.Controls.Add(this.tabControl);
+      this.Controls.Add(this.cancelButton);
+      this.Controls.Add(this.okButton);
+      this.Name = "DataTableVisualPropertiesDialog";
+      this.ShowIcon = false;
+      this.Text = "Customize Visual Properties";
+      this.tabControl.ResumeLayout(false);
+      this.seriesTabPage.ResumeLayout(false);
+      this.splitContainer.Panel1.ResumeLayout(false);
+      this.splitContainer.Panel2.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
+      this.splitContainer.ResumeLayout(false);
+      this.chartTabPage.ResumeLayout(false);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button okButton;
+    private System.Windows.Forms.Button cancelButton;
+    private System.Windows.Forms.TabControl tabControl;
+    private System.Windows.Forms.TabPage seriesTabPage;
+    private System.Windows.Forms.SplitContainer splitContainer;
+    private System.Windows.Forms.ListView seriesListView;
+    private System.Windows.Forms.TabPage chartTabPage;
+    private DataRowVisualPropertiesControl dataRowVisualPropertiesControl;
+    private DataTableVisualPropertiesControl dataTableVisualPropertiesControl;
+    private System.Windows.Forms.Button downButton;
+    private System.Windows.Forms.Button upButton;
+  }
+}
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.cs	(revision 6342)
@@ -0,0 +1,136 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using HeuristicLab.Common.Resources;
+
+namespace HeuristicLab.Analysis.Views {
+  public partial class DataTableVisualPropertiesDialog : Form {
+    protected bool SuppressEvents { get; set; }
+    protected DataTable Content { get; private set; }
+    private DataTableVisualProperties originalDataTableVPs;
+    private Dictionary<string, DataRowVisualProperties> originalDataRowVPs;
+
+    public DataTableVisualPropertiesDialog(DataTable dataTable) {
+      InitializeComponent();
+      upButton.Text = string.Empty;
+      upButton.Image = VSImageLibrary.ArrowUp;
+      downButton.Text = string.Empty;
+      downButton.Image = VSImageLibrary.ArrowDown;
+      Content = dataTable;
+      originalDataTableVPs = (DataTableVisualProperties)Content.VisualProperties.Clone();
+      originalDataRowVPs = new Dictionary<string, DataRowVisualProperties>();
+      foreach (DataRow row in Content.Rows)
+        originalDataRowVPs.Add(row.Name, (DataRowVisualProperties)row.VisualProperties.Clone());
+      seriesListView.Items.Clear();
+      seriesListView.SmallImageList = new ImageList();
+      seriesListView.SmallImageList.Images.Add(VSImageLibrary.Graph);
+      FillSeriesListView();
+      dataTableVisualPropertiesControl.Content = Content.VisualProperties;
+    }
+
+    private void FillSeriesListView() {
+      seriesListView.SelectedIndices.Clear();
+      foreach (DataRow row in Content.Rows) {
+        seriesListView.Items.Add(new ListViewItem(row.Name, 0));
+      }
+      seriesListView.SelectedIndices.Add(0);
+    }
+
+    private void seriesListView_SelectedIndexChanged(object sender, System.EventArgs e) {
+      if (!SuppressEvents) {
+        if (seriesListView.SelectedItems.Count != 1) {
+          dataRowVisualPropertiesControl.Content = null;
+        } else {
+          string rowName = seriesListView.SelectedItems[0].Text;
+          dataRowVisualPropertiesControl.Content = Content.Rows[rowName].VisualProperties;
+        }
+      }
+    }
+
+    private void okButton_Click(object sender, System.EventArgs e) {
+      DialogResult = DialogResult.OK;
+      Close();
+    }
+
+    private void cancelButton_Click(object sender, System.EventArgs e) {
+      DialogResult = DialogResult.Cancel;
+      foreach (DataRow row in Content.Rows) {
+        row.VisualProperties = originalDataRowVPs[row.Name];
+      }
+      Content.VisualProperties = originalDataTableVPs;
+      Close();
+    }
+
+    private void upButton_Click(object sender, System.EventArgs e) {
+      if (seriesListView.SelectedIndices.Count == 1 && seriesListView.SelectedIndices[0] > 0) {
+        int index = seriesListView.SelectedIndices[0];
+        SuppressEvents = true;
+        try {
+          seriesListView.BeginUpdate();
+          ListViewItem selectedSeriesItem = seriesListView.Items[index];
+          seriesListView.Items.RemoveAt(index);
+          ListViewItem temp = seriesListView.Items[index - 1];
+          seriesListView.Items.RemoveAt(index - 1);
+          seriesListView.Items.Insert(index - 1, selectedSeriesItem);
+          seriesListView.Items.Insert(index, temp);
+          seriesListView.SelectedIndices.Clear();
+          seriesListView.EndUpdate();
+        } finally { SuppressEvents = false; }
+        seriesListView.SelectedIndices.Add(index - 1);
+        UpdateAllSeriesPositions();
+      }
+    }
+
+    private void downButton_Click(object sender, System.EventArgs e) {
+      if (seriesListView.SelectedIndices.Count == 1 && seriesListView.SelectedIndices[0] < seriesListView.Items.Count - 1) {
+        int index = seriesListView.SelectedIndices[0];
+        SuppressEvents = true;
+        try {
+          seriesListView.BeginUpdate();
+          ListViewItem temp = seriesListView.Items[index + 1];
+          seriesListView.Items.RemoveAt(index + 1);
+          ListViewItem selectedSeriesItem = seriesListView.Items[index];
+          seriesListView.Items.RemoveAt(index);
+          seriesListView.Items.Insert(index, temp);
+          seriesListView.Items.Insert(index + 1, selectedSeriesItem);
+          seriesListView.SelectedIndices.Clear();
+          seriesListView.EndUpdate();
+        } finally { SuppressEvents = false; }
+        seriesListView.SelectedIndices.Add(index + 1);
+        UpdateAllSeriesPositions();
+      }
+    }
+
+    #region Helpers
+    private void UpdateAllSeriesPositions() {
+      Dictionary<string, DataRow> rows = Content.Rows.ToDictionary(x => x.Name);
+      Content.Rows.Clear();
+      for (int i = 0; i < seriesListView.Items.Count; i++) {
+        ListViewItem item = seriesListView.Items[i];
+        Content.Rows.Add(rows[item.Text]);
+      }
+    }
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.resx
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.resx	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/DataTableVisualPropertiesDialog.resx	(revision 6342)
@@ -0,0 +1,120 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj	(revision 6342)
@@ -120,4 +120,22 @@
       <DependentUpon>AlleleFrequencyCollectionView.cs</DependentUpon>
     </Compile>
+    <Compile Include="DataRowVisualPropertiesControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="DataRowVisualPropertiesControl.Designer.cs">
+      <DependentUpon>DataRowVisualPropertiesControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DataTableVisualPropertiesControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="DataTableVisualPropertiesControl.Designer.cs">
+      <DependentUpon>DataTableVisualPropertiesControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DataTableVisualPropertiesDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="DataTableVisualPropertiesDialog.Designer.cs">
+      <DependentUpon>DataTableVisualPropertiesDialog.cs</DependentUpon>
+    </Compile>
     <Compile Include="HeatMapHistoryView.cs">
       <SubType>UserControl</SubType>
@@ -171,4 +189,8 @@
       <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
       <Name>HeuristicLab.Collections-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
+      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
+      <Name>HeuristicLab.Common.Resources-3.3</Name>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
@@ -235,4 +257,16 @@
   </ItemGroup>
   <ItemGroup>
+    <EmbeddedResource Include="DataRowVisualPropertiesControl.resx">
+      <DependentUpon>DataRowVisualPropertiesControl.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="DataTableView.resx">
+      <DependentUpon>DataTableView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="DataTableVisualPropertiesControl.resx">
+      <DependentUpon>DataTableVisualPropertiesControl.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="DataTableVisualPropertiesDialog.resx">
+      <DependentUpon>DataTableVisualPropertiesDialog.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="HeatMapView.resx">
       <DependentUpon>HeatMapView.cs</DependentUpon>
Index: /trunk/sources/HeuristicLab.Analysis.Views/3.3/HeuristicLabAnalysisViewsPlugin.cs.frame
===================================================================
--- /trunk/sources/HeuristicLab.Analysis.Views/3.3/HeuristicLabAnalysisViewsPlugin.cs.frame	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis.Views/3.3/HeuristicLabAnalysisViewsPlugin.cs.frame	(revision 6342)
@@ -31,4 +31,5 @@
   [PluginDependency("HeuristicLab.Collections", "3.3")]
   [PluginDependency("HeuristicLab.Common", "3.3")]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
   [PluginDependency("HeuristicLab.Core", "3.3")]
   [PluginDependency("HeuristicLab.Core.Views", "3.3")]
Index: /trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataRowVisualProperties.cs	(revision 6342)
@@ -36,5 +36,16 @@
       Columns,
       Points,
-      Bars
+      Bars,
+      Histogram
+    }
+    #endregion
+    #region LineStyle
+    public enum DataRowLineStyle {
+      Dash,
+      DashDot,
+      DashDotDot,
+      Dot,
+      NotSet,
+      Solid
     }
     #endregion
@@ -60,4 +71,14 @@
       }
     }
+    private bool secondXAxis;
+    public bool SecondXAxis {
+      get { return secondXAxis; }
+      set {
+        if (secondXAxis != value) {
+          secondXAxis = value;
+          OnPropertyChanged("SecondXAxis");
+        }
+      }
+    }
     private Color color;
     public Color Color {
@@ -70,4 +91,14 @@
       }
     }
+    private DataRowLineStyle lineStyle;
+    public DataRowLineStyle LineStyle {
+      get { return lineStyle; }
+      set {
+        if (lineStyle != value) {
+          lineStyle = value;
+          OnPropertyChanged("LineStyle");
+        }
+      }
+    }
     private bool startIndexZero;
     public bool StartIndexZero {
@@ -77,4 +108,34 @@
           startIndexZero = value;
           OnPropertyChanged("StartIndexZero");
+        }
+      }
+    }
+    private int lineWidth;
+    public int LineWidth {
+      get { return lineWidth; }
+      set {
+        if (lineWidth != value) {
+          lineWidth = value;
+          OnPropertyChanged("LineWidth");
+        }
+      }
+    }
+    private int bins;
+    public int Bins {
+      get { return bins; }
+      set {
+        if (bins != value) {
+          bins = value;
+          OnPropertyChanged("Bins");
+        }
+      }
+    }
+    private bool exactBins;
+    public bool ExactBins {
+      get { return exactBins; }
+      set {
+        if (exactBins != value) {
+          exactBins = value;
+          OnPropertyChanged("ExactBins");
         }
       }
@@ -92,4 +153,9 @@
       set { secondYAxis = value; }
     }
+    [Storable(Name = "SecondXAxis")]
+    private bool StorableSecondXAxis {
+      get { return secondXAxis; }
+      set { secondXAxis = value; }
+    }
     [Storable(Name = "Color")]
     private Color StorableColor {
@@ -97,8 +163,28 @@
       set { color = value; }
     }
+    [Storable(Name = "LineStyle")]
+    private DataRowLineStyle StorableLineStyle {
+      get { return lineStyle; }
+      set { lineStyle = value; }
+    }
     [Storable(Name = "StartIndexZero")]
     private bool StorableStartIndexZero {
       get { return startIndexZero; }
       set { startIndexZero = value; }
+    }
+    [Storable(Name = "LineWidth")]
+    private int StorableLineWidth {
+      get { return lineWidth; }
+      set { lineWidth = value; }
+    }
+    [Storable(Name = "Bins")]
+    private int StorableBins {
+      get { return bins; }
+      set { bins = value; }
+    }
+    [Storable(Name = "ExactBins")]
+    private bool StorableExactBins {
+      get { return exactBins; }
+      set { exactBins = value; }
     }
     #endregion
@@ -110,12 +196,22 @@
       this.chartType = original.chartType;
       this.secondYAxis = original.secondYAxis;
+      this.secondXAxis = original.secondXAxis;
       this.color = original.color;
+      this.lineStyle = original.lineStyle;
       this.startIndexZero = original.startIndexZero;
+      this.lineWidth = original.lineWidth;
+      this.bins = original.bins;
+      this.exactBins = original.exactBins;
     }
     public DataRowVisualProperties() {
       chartType = DataRowChartType.Line;
       secondYAxis = false;
+      secondXAxis = false;
       color = Color.Empty;
+      lineStyle = DataRowLineStyle.Solid;
       startIndexZero = false;
+      lineWidth = 1;
+      bins = 10;
+      exactBins = false;
     }
 
Index: /trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/DataTableVisualProperties.cs	(revision 6342)
@@ -21,4 +21,5 @@
 
 using System.ComponentModel;
+using System.Drawing;
 using HeuristicLab.Common;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
@@ -30,4 +31,46 @@
   [StorableClass]
   public class DataTableVisualProperties : DeepCloneable, INotifyPropertyChanged {
+    private Font titleFont;
+    public Font TitleFont {
+      get { return titleFont; }
+      set {
+        if (titleFont == null || value == null
+          || titleFont.Name != value.Name || titleFont.Size != value.Size || titleFont.Style != value.Style) {
+          titleFont = value;
+          OnPropertyChanged("TitleFont");
+        }
+      }
+    }
+    private Color titleColor;
+    public Color TitleColor {
+      get { return titleColor; }
+      set {
+        if (titleColor != value) {
+          titleColor = value;
+          OnPropertyChanged("TitleFontColor");
+        }
+      }
+    }
+    private Font axisTitleFont;
+    public Font AxisTitleFont {
+      get { return axisTitleFont; }
+      set {
+        if (axisTitleFont == null || axisTitleFont == null
+          || axisTitleFont.Name != value.Name || axisTitleFont.Size != value.Size || axisTitleFont.Style != value.Style) {
+          axisTitleFont = value;
+          OnPropertyChanged("AxisTitleFont");
+        }
+      }
+    }
+    private Color axisTitleColor;
+    public Color AxisTitleColor {
+      get { return axisTitleColor; }
+      set {
+        if (axisTitleColor != value) {
+          axisTitleColor = value;
+          OnPropertyChanged("AxisTitleColor");
+        }
+      }
+    }
     private string xAxisTitle;
     public string XAxisTitle {
@@ -54,4 +97,16 @@
     }
 
+    private string secondXAxisTitle;
+    public string SecondXAxisTitle {
+      get { return secondXAxisTitle; }
+      set {
+        if (value == null) value = string.Empty;
+        if (secondXAxisTitle != value) {
+          secondXAxisTitle = value;
+          OnPropertyChanged("SecondXAxisTitle");
+        }
+      }
+    }
+
     private string secondYAxisTitle;
     public string SecondYAxisTitle {
@@ -66,5 +121,209 @@
     }
 
+    private bool xAxisMinimumAuto;
+    public bool XAxisMinimumAuto {
+      get { return xAxisMinimumAuto; }
+      set {
+        if (xAxisMinimumAuto != value) {
+          xAxisMinimumAuto = value;
+          if (value) xAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("XAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool xAxisMaximumAuto;
+    public bool XAxisMaximumAuto {
+      get { return xAxisMaximumAuto; }
+      set {
+        if (xAxisMaximumAuto != value) {
+          xAxisMaximumAuto = value;
+          if (value) xAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("XAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double xAxisMinimumFixedValue;
+    public double XAxisMinimumFixedValue {
+      get { return xAxisMinimumFixedValue; }
+      set {
+        if (xAxisMinimumFixedValue != value) {
+          xAxisMinimumFixedValue = value;
+          OnPropertyChanged("XAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double xAxisMaximumFixedValue;
+    public double XAxisMaximumFixedValue {
+      get { return xAxisMaximumFixedValue; }
+      set {
+        if (xAxisMaximumFixedValue != value) {
+          xAxisMaximumFixedValue = value;
+          OnPropertyChanged("XAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool secondXAxisMinimumAuto;
+    public bool SecondXAxisMinimumAuto {
+      get { return secondXAxisMinimumAuto; }
+      set {
+        if (secondXAxisMinimumAuto != value) {
+          secondXAxisMinimumAuto = value;
+          if (value) secondXAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("SecondXAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool secondXAxisMaximumAuto;
+    public bool SecondXAxisMaximumAuto {
+      get { return secondXAxisMaximumAuto; }
+      set {
+        if (secondXAxisMaximumAuto != value) {
+          secondXAxisMaximumAuto = value;
+          if (value) secondXAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("SecondXAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double secondXAxisMinimumFixedValue;
+    public double SecondXAxisMinimumFixedValue {
+      get { return secondXAxisMinimumFixedValue; }
+      set {
+        if (secondXAxisMinimumFixedValue != value) {
+          secondXAxisMinimumFixedValue = value;
+          OnPropertyChanged("SecondXAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double secondXAxisMaximumFixedValue;
+    public double SecondXAxisMaximumFixedValue {
+      get { return secondXAxisMaximumFixedValue; }
+      set {
+        if (secondXAxisMaximumFixedValue != value) {
+          secondXAxisMaximumFixedValue = value;
+          OnPropertyChanged("SecondXAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool yAxisMinimumAuto;
+    public bool YAxisMinimumAuto {
+      get { return yAxisMinimumAuto; }
+      set {
+        if (yAxisMinimumAuto != value) {
+          yAxisMinimumAuto = value;
+          if (value) yAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("YAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool yAxisMaximumAuto;
+    public bool YAxisMaximumAuto {
+      get { return yAxisMaximumAuto; }
+      set {
+        if (yAxisMaximumAuto != value) {
+          yAxisMaximumAuto = value;
+          if (value) yAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("YAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double yAxisMinimumFixedValue;
+    public double YAxisMinimumFixedValue {
+      get { return yAxisMinimumFixedValue; }
+      set {
+        if (yAxisMinimumFixedValue != value) {
+          yAxisMinimumFixedValue = value;
+          OnPropertyChanged("YAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double yAxisMaximumFixedValue;
+    public double YAxisMaximumFixedValue {
+      get { return yAxisMaximumFixedValue; }
+      set {
+        if (yAxisMaximumFixedValue != value) {
+          yAxisMaximumFixedValue = value;
+          OnPropertyChanged("YAxisMaximumFixedValue");
+        }
+      }
+    }
+
+    private bool secondYAxisMinimumAuto;
+    public bool SecondYAxisMinimumAuto {
+      get { return secondYAxisMinimumAuto; }
+      set {
+        if (secondYAxisMinimumAuto != value) {
+          secondYAxisMinimumAuto = value;
+          if (value) secondYAxisMinimumFixedValue = double.NaN;
+          OnPropertyChanged("SecondYAxisMinimumAuto");
+        }
+      }
+    }
+
+    private bool secondYAxisMaximumAuto;
+    public bool SecondYAxisMaximumAuto {
+      get { return secondYAxisMaximumAuto; }
+      set {
+        if (secondYAxisMaximumAuto != value) {
+          secondYAxisMaximumAuto = value;
+          if (value) secondYAxisMaximumFixedValue = double.NaN;
+          OnPropertyChanged("SecondYAxisMaximumAuto");
+        }
+      }
+    }
+
+    private double secondYAxisMinimumFixedValue;
+    public double SecondYAxisMinimumFixedValue {
+      get { return secondYAxisMinimumFixedValue; }
+      set {
+        if (secondYAxisMinimumFixedValue != value) {
+          secondYAxisMinimumFixedValue = value;
+          OnPropertyChanged("SecondYAxisMinimumFixedValue");
+        }
+      }
+    }
+
+    private double secondYAxisMaximumFixedValue;
+    public double SecondYAxisMaximumFixedValue {
+      get { return secondYAxisMaximumFixedValue; }
+      set {
+        if (secondYAxisMaximumFixedValue != value) {
+          secondYAxisMaximumFixedValue = value;
+          OnPropertyChanged("SecondYAxisMaximumFixedValue");
+        }
+      }
+    }
+
     #region Persistence Properties
+    [Storable(Name = "TitleFont")]
+    private Font StorableTitleFont {
+      get { return titleFont; }
+      set { titleFont = value; }
+    }
+    [Storable(Name = "TitleColor")]
+    private Color StorableTitleColor {
+      get { return titleColor; }
+      set { titleColor = value; }
+    }
+    [Storable(Name = "AxisTitleFont")]
+    private Font StorableAxisTitleFont {
+      get { return axisTitleFont; }
+      set { axisTitleFont = value; }
+    }
+    [Storable(Name = "AxisTitleColor")]
+    private Color StorableAxisTitleColor {
+      get { return axisTitleColor; }
+      set { axisTitleColor = value; }
+    }
     [Storable(Name = "XAxisTitle")]
     private string StorableXAxisTitle {
@@ -77,4 +336,9 @@
       set { yAxisTitle = value; }
     }
+    [Storable(Name = "SecondXAxisTitle")]
+    private string StorableSecondXAxisTitle {
+      get { return secondXAxisTitle; }
+      set { secondXAxisTitle = value; }
+    }
     [Storable(Name = "SecondYAxisTitle")]
     private string StorableSecondYAxisTitle {
@@ -82,4 +346,84 @@
       set { secondYAxisTitle = value; }
     }
+    [Storable(Name = "XAxisMinimumAuto")]
+    private bool StorableXAxisMinimumAuto {
+      get { return xAxisMinimumAuto; }
+      set { xAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "XAxisMaximumAuto")]
+    private bool StorableXAxisMaximumAuto {
+      get { return xAxisMaximumAuto; }
+      set { xAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "XAxisMinimumFixedValue")]
+    private double StorableXAxisMinimumFixedValue {
+      get { return xAxisMinimumFixedValue; }
+      set { xAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "XAxisMaximumFixedValue")]
+    private double StorableXAxisMaximumFixedValue {
+      get { return xAxisMaximumFixedValue; }
+      set { xAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "SecondXAxisMinimumAuto")]
+    private bool StorableSecondXAxisMinimumAuto {
+      get { return secondXAxisMinimumAuto; }
+      set { secondXAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "SecondXAxisMaximumAuto")]
+    private bool StorableSecondXAxisMaximumAuto {
+      get { return secondXAxisMaximumAuto; }
+      set { secondXAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "SecondXAxisMinimumFixedValue")]
+    private double StorableSecondXAxisMinimumFixedValue {
+      get { return secondXAxisMinimumFixedValue; }
+      set { secondXAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "SecondXAxisMaximumFixedValue")]
+    private double StorableSecondXAxisMaximumFixedValue {
+      get { return secondXAxisMaximumFixedValue; }
+      set { secondXAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "YAxisMinimumAuto")]
+    private bool StorableYAxisMinimumAuto {
+      get { return yAxisMinimumAuto; }
+      set { yAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "YAxisMaximumAuto")]
+    private bool StorableYAxisMaximumAuto {
+      get { return yAxisMaximumAuto; }
+      set { yAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "YAxisMinimumFixedValue")]
+    private double StorableYAxisMinimumFixedValue {
+      get { return yAxisMinimumFixedValue; }
+      set { yAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "YAxisMaximumFixedValue")]
+    private double StorableYAxisMaximumFixedValue {
+      get { return yAxisMaximumFixedValue; }
+      set { yAxisMaximumFixedValue = value; }
+    }
+    [Storable(Name = "SecondYAxisMinimumAuto")]
+    private bool StorableSecondYAxisMinimumAuto {
+      get { return secondYAxisMinimumAuto; }
+      set { secondYAxisMinimumAuto = value; }
+    }
+    [Storable(Name = "SecondYAxisMaximumAuto")]
+    private bool StorableSecondYAxisMaximumAuto {
+      get { return secondYAxisMaximumAuto; }
+      set { secondYAxisMaximumAuto = value; }
+    }
+    [Storable(Name = "SecondYAxisMinimumFixedValue")]
+    private double StorableSecondYAxisMinimumFixedValue {
+      get { return secondYAxisMinimumFixedValue; }
+      set { secondYAxisMinimumFixedValue = value; }
+    }
+    [Storable(Name = "SecondYAxisMaximumFixedValue")]
+    private double StorableSecondYAxisMaximumFixedValue {
+      get { return secondYAxisMaximumFixedValue; }
+      set { secondYAxisMaximumFixedValue = value; }
+    }
     #endregion
 
@@ -88,12 +432,52 @@
     protected DataTableVisualProperties(DataTableVisualProperties original, Cloner cloner)
       : base(original, cloner) {
+      if (original.titleFont != null)
+        this.titleFont = (Font)original.titleFont.Clone();
+      if (original.axisTitleFont != null)
+        this.axisTitleFont = (Font)original.axisTitleFont.Clone();
       this.xAxisTitle = original.xAxisTitle;
       this.yAxisTitle = original.yAxisTitle;
+      this.secondXAxisTitle = original.secondXAxisTitle;
       this.secondYAxisTitle = original.secondYAxisTitle;
+      this.xAxisMinimumAuto = original.xAxisMinimumAuto;
+      this.xAxisMinimumFixedValue = original.xAxisMinimumFixedValue;
+      this.xAxisMaximumAuto = original.xAxisMaximumAuto;
+      this.xAxisMaximumFixedValue = original.xAxisMaximumFixedValue;
+      this.secondXAxisMinimumAuto = original.secondXAxisMinimumAuto;
+      this.secondXAxisMinimumFixedValue = original.secondXAxisMinimumFixedValue;
+      this.secondXAxisMaximumAuto = original.secondXAxisMaximumAuto;
+      this.secondXAxisMaximumFixedValue = original.secondXAxisMaximumFixedValue;
+      this.yAxisMinimumAuto = original.yAxisMinimumAuto;
+      this.yAxisMinimumFixedValue = original.yAxisMinimumFixedValue;
+      this.yAxisMaximumAuto = original.yAxisMaximumAuto;
+      this.yAxisMaximumFixedValue = original.yAxisMaximumFixedValue;
+      this.secondYAxisMinimumAuto = original.secondYAxisMinimumAuto;
+      this.secondYAxisMinimumFixedValue = original.secondYAxisMinimumFixedValue;
+      this.secondYAxisMaximumAuto = original.secondYAxisMaximumAuto;
+      this.secondYAxisMaximumFixedValue = original.secondYAxisMaximumFixedValue;
     }
     public DataTableVisualProperties() {
+      titleColor = Color.Black;
+      axisTitleColor = Color.Black;
       this.xAxisTitle = string.Empty;
       this.yAxisTitle = string.Empty;
+      this.secondXAxisTitle = string.Empty;
       this.secondYAxisTitle = string.Empty;
+      this.xAxisMinimumAuto = true;
+      this.xAxisMinimumFixedValue = double.NaN;
+      this.xAxisMaximumAuto = true;
+      this.xAxisMaximumFixedValue = double.NaN;
+      this.secondXAxisMinimumAuto = true;
+      this.secondXAxisMinimumFixedValue = double.NaN;
+      this.secondXAxisMaximumAuto = true;
+      this.secondXAxisMaximumFixedValue = double.NaN;
+      this.yAxisMinimumAuto = true;
+      this.yAxisMinimumFixedValue = double.NaN;
+      this.yAxisMaximumAuto = true;
+      this.yAxisMaximumFixedValue = double.NaN;
+      this.secondYAxisMinimumAuto = true;
+      this.secondYAxisMinimumFixedValue = double.NaN;
+      this.secondYAxisMaximumAuto = true;
+      this.secondYAxisMaximumFixedValue = double.NaN;
     }
 
Index: /trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 6342)
@@ -138,4 +138,5 @@
     <Compile Include="HeuristicLabAnalysisPlugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="QualityAnalysis\QualityDistributionAnalyzer.cs" />
     <Compile Include="ValueAnalysis\MinAverageMaxValueAnalyzer.cs" />
     <Compile Include="ValueAnalysis\MinAverageMaxValueCalculator.cs" />
Index: /trunk/sources/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis/3.3/MultidimensionalScaling/MultidimensionalScaling.cs	(revision 6342)
@@ -68,5 +68,5 @@
     /// In every iteration it tries to find the best location for every item.</param>
     /// <returns>A Nx2 matrix where the first column represents the x- and the second column the y coordinates.</returns>
-    public static DoubleMatrix KruskalShepard(DoubleMatrix dissimilarities, DoubleMatrix coordinates, int maximumIterations = 20) {
+    public static DoubleMatrix KruskalShepard(DoubleMatrix dissimilarities, DoubleMatrix coordinates, int maximumIterations = 10) {
       int dimension = dissimilarities.Rows;
       if (dimension != dissimilarities.Columns || coordinates.Rows != dimension) throw new ArgumentException("The number of coordinates and the number of rows and columns in the dissimilarities matrix do not match.");
@@ -75,8 +75,8 @@
       double epsf = 0;
       double epsx = 0;
-      int maxits = 100;
-      alglib.mincgstate state = null;
-      alglib.mincgreport rep;
+      int maxits = 0;
 
+      alglib.minlmstate state;
+      alglib.minlmreport rep;
       for (int iterations = 0; iterations < maximumIterations; iterations++) {
         bool changed = false;
@@ -85,12 +85,8 @@
 
           try {
-            if ((iterations == 0 && i == 0)) {
-              alglib.mincgcreate(c, out state);
-              alglib.mincgsetcond(state, epsg, epsf, epsx, maxits);
-            } else {
-              alglib.mincgrestartfrom(state, c);
-            }
-            alglib.mincgoptimize(state, StressGradient, null, new Info(coordinates, dissimilarities, i));
-            alglib.mincgresults(state, out c, out rep);
+            alglib.minlmcreatevj(dimension - 1, c, out state);
+            alglib.minlmsetcond(state, epsg, epsf, epsx, maxits);
+            alglib.minlmoptimize(state, StressFitness, StressJacobian, null, new Info(coordinates, dissimilarities, i));
+            alglib.minlmresults(state, out c, out rep);
           } catch (alglib.alglibexception) { }
           if (!double.IsNaN(c[0]) && !double.IsNaN(c[1])) {
@@ -105,16 +101,26 @@
     }
 
-    // computes the function and the gradient of the raw stress function.
-    private static void StressGradient(double[] x, ref double func, double[] grad, object obj) {
-      func = 0; grad[0] = 0; grad[1] = 0;
+    private static void StressFitness(double[] x, double[] fi, object obj) {
       Info info = (obj as Info);
       for (int i = 0; i < info.Coordinates.Rows; i++) {
-        double c = info.Dissimilarities[info.Row, i];
+        double f = Stress(x, info.Dissimilarities[info.Row, i], info.Coordinates[i, 0], info.Coordinates[i, 1]);
+        if (i < info.Row) fi[i] = f;
+        else if (i > info.Row) fi[i - 1] = f;
+      }
+    }
+
+    private static void StressJacobian(double[] x, double[] fi, double[,] jac, object obj) {
+      Info info = (obj as Info);
+      int idx = 0;
+      for (int i = 0; i < info.Coordinates.Rows; i++) {
         if (i != info.Row) {
+          double c = info.Dissimilarities[info.Row, i];
           double a = info.Coordinates[i, 0];
           double b = info.Coordinates[i, 1];
-          func += Stress(x, c, a, b);
-          grad[0] += ((2 * x[0] - 2 * a) * Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a) - 2 * c * x[0] + 2 * a * c) / Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a);
-          grad[1] += ((2 * x[1] - 2 * b) * Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a) - 2 * c * x[1] + 2 * b * c) / Math.Sqrt(x[1] * x[1] - 2 * b * x[1] + x[0] * x[0] - 2 * a * x[0] + b * b + a * a);
+          double f = Stress(x, c, a, b);
+          fi[idx] = f;
+          jac[idx, 0] = 2 * (x[0] - a) * (Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1])) - c) / Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1]));
+          jac[idx, 1] = 2 * (x[1] - b) * (Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1])) - c) / Math.Sqrt((a - x[0]) * (a - x[0]) + (b - x[1]) * (b - x[1]));
+          idx++;
         }
       }
Index: /trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Analysis/3.3/QualityAnalysis/QualityDistributionAnalyzer.cs	(revision 6342)
@@ -0,0 +1,135 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis.QualityAnalysis {
+  [Item("QualityDistributionAnalyzer", "Analyzes the distribution of the quality values in that it adds a Histogram of them into the result collection.")]
+  [StorableClass]
+  public class QualityDistributionAnalyzer : SingleSuccessorOperator, IAnalyzer, IIterationBasedOperator {
+
+    #region Parameter properties
+    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
+      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+    public IValueLookupParameter<ResultCollection> ResultsParameter {
+      get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+    private ValueParameter<StringValue> HistogramNameParameter {
+      get { return (ValueParameter<StringValue>)Parameters["HistogramName"]; }
+    }
+    private ValueParameter<BoolValue> StoreHistoryParameter {
+      get { return (ValueParameter<BoolValue>)Parameters["StoreHistory"]; }
+    }
+    public ILookupParameter<IntValue> IterationsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
+    }
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+    #endregion
+
+    public string HistogramName {
+      get { return HistogramNameParameter.Value.Value; }
+      set { HistogramNameParameter.Value.Value = value; }
+    }
+
+    public bool StoreHistory {
+      get { return StoreHistoryParameter.Value.Value; }
+      set { StoreHistoryParameter.Value.Value = value; }
+    }
+
+    [StorableConstructor]
+    protected QualityDistributionAnalyzer(bool deserializing) : base(deserializing) { }
+    protected QualityDistributionAnalyzer(QualityDistributionAnalyzer original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public QualityDistributionAnalyzer()
+      : base() {
+      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The value which represents the quality of a solution."));
+      Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The results collection where the analysis values should be stored."));
+      Parameters.Add(new FixedValueParameter<StringValue>("HistogramName", "The name of the histogram that gets injected in to the results collection.", new StringValue("Quality Distribution")));
+      Parameters.Add(new FixedValueParameter<BoolValue>("StoreHistory", "True if the history should be stored in addition to the current distribution", new BoolValue(false)));
+      Parameters.Add(new LookupParameter<IntValue>("Iterations", "Optional: A value indicating the current iteration."));
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "Unused", new IntValue(-1)));
+
+      QualityParameter.Hidden = true;
+      ResultsParameter.Hidden = true;
+      IterationsParameter.Hidden = true;
+      MaximumIterationsParameter.Hidden = true;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QualityDistributionAnalyzer(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      DataTable qualityDistribution = null;
+      ResultCollection results = ResultsParameter.ActualValue;
+      string description = "Shows the quality distributions in the current population.";
+      if (results.ContainsKey(HistogramName)) {
+        qualityDistribution = results[HistogramName].Value as DataTable;
+      } else {
+        qualityDistribution = new DataTable("Population Quality Distribution", description);
+        qualityDistribution.VisualProperties.XAxisTitle = QualityParameter.ActualName;
+        qualityDistribution.VisualProperties.YAxisTitle = "Frequency";
+        results.Add(new Result(HistogramName, description, qualityDistribution));
+      }
+      DataRow row;
+      if (!qualityDistribution.Rows.TryGetValue("QualityDistribution", out row)) {
+        row = new DataRow("QualityDistribution");
+        row.VisualProperties.ChartType = DataRowVisualProperties.DataRowChartType.Histogram;
+        qualityDistribution.Rows.Add(row);
+      }
+      var qualities = QualityParameter.ActualValue;
+      row.Values.Replace(qualities.Select(x => x.Value));
+
+      if (StoreHistory) {
+        string historyResultName = HistogramName + " History";
+        DataTableHistory qdHistory = null;
+        if (results.ContainsKey(historyResultName)) {
+          qdHistory = results[historyResultName].Value as DataTableHistory;
+        } else {
+          qdHistory = new DataTableHistory();
+          results.Add(new Result(historyResultName, qdHistory));
+        }
+        DataTable table = (DataTable)qualityDistribution.Clone();
+        IntValue iteration = IterationsParameter.ActualValue;
+        if (iteration != null) {
+          string iterationName = IterationsParameter.ActualName;
+          if (iterationName.EndsWith("s")) iterationName = iterationName.Remove(iterationName.Length - 1);
+          string appendix = " at " + iterationName + " " + iteration.Value.ToString();
+          table.Name += appendix;
+          table.Rows["QualityDistribution"].Name += appendix;
+        }
+        qdHistory.Add(table);
+      }
+      return base.Apply();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs
===================================================================
--- /trunk/sources/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Analysis/3.3/Tests/MultidimensionalScalingTest.cs	(revision 6342)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Globalization;
 using HeuristicLab.Data;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -42,6 +43,9 @@
       distances3[0, 2] = distances3[2, 0] = 6.4;
       distances3[1, 2] = distances3[2, 1] = 5;
-      stress = MultidimensionalScaling.CalculateNormalizedStress(distances3,
-        MultidimensionalScaling.KruskalShepard(distances3));
+      DoubleMatrix coords3 = MultidimensionalScaling.KruskalShepard(distances3);
+      Console.WriteLine("Coordinates: ");
+      Console.WriteLine("A = ({0}, {1}), B = ({2}, {3}), C = ({4}, {5})", coords3[0, 0], coords3[0, 1], coords3[1, 0], coords3[1, 1], coords3[2, 0], coords3[2, 1]);
+      stress = MultidimensionalScaling.CalculateNormalizedStress(distances3, coords3);
+      Console.WriteLine("Stress = " + stress.ToString(CultureInfo.InvariantCulture.NumberFormat));
       Assert.IsTrue(stress < 0.1);
       DoubleMatrix distances4 = new DoubleMatrix(4, 4);
Index: /trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs
===================================================================
--- /trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Collections/3.3/ObservableList.cs	(revision 6342)
@@ -24,4 +24,5 @@
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Linq;
 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
@@ -211,4 +212,27 @@
     }
 
+    /// <summary>
+    /// Performs a Clear and an AddRange, but does not fire separate events for those operations
+    /// </summary>
+    /// <param name="collection"></param>
+    public void Replace(IEnumerable<T> collection) {
+      List<IndexedItem<T>> oldItems = null;
+      if (list.Any()) oldItems = list.Select((x, i) => new IndexedItem<T>(i, x)).ToList();
+      else oldItems = new List<IndexedItem<T>>();
+
+      int oldCapacity = list.Capacity;
+      list.Clear();
+      list.AddRange(collection);
+
+      List<IndexedItem<T>> items = null;
+      if (list.Any()) items = list.Select((x, i) => new IndexedItem<T>(i, x)).ToList();
+      else items = new List<IndexedItem<T>>();
+
+      if (oldCapacity != list.Capacity) OnPropertyChanged("Capacity");
+      OnPropertyChanged("Item[]");
+      if (oldItems.Count != items.Count) OnPropertyChanged("Count");
+      OnItemsReplaced(items, oldItems);
+    }
+
     public bool Remove(T item) {
       int index = list.IndexOf(item);
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Crossovers/UniformLikeCrossover.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Crossovers/UniformLikeCrossover.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Crossovers/UniformLikeCrossover.cs	(revision 6342)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [Item("UniformLikeCrossover", "The ULX crossover tries to maintain the position in the permutation. It randomly chooses from left to right one of its parents' alleles at each position. Missing entries are then filled randomly later. It is described in Tate, D. M. and Smith, A. E. 1995. A genetic approach to the quadratic assignment problem. Computers & Operations Research, vol. 22, pp. 73-83.")]
+  [StorableClass]
+  public class UniformLikeCrossover : PermutationCrossover {
+    [StorableConstructor]
+    protected UniformLikeCrossover(bool deserializing) : base(deserializing) { }
+    protected UniformLikeCrossover(UniformLikeCrossover original, Cloner cloner) : base(original, cloner) { }
+    public UniformLikeCrossover() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new UniformLikeCrossover(this, cloner);
+    }
+
+    public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) {
+      if (parent1.Length != parent2.Length) throw new ArgumentException("parent1 and parent2 are of different length.");
+      int length = parent1.Length;
+      int[] child = new int[length];
+      bool[] numberCopied = new bool[length];
+      List<int> unoccupied = new List<int>();
+
+      for (int i = 0; i < length; i++) {
+        bool copied = true;
+        if (parent1[i] == parent2[i]) {
+          child[i] = parent1[i];
+        } else if (!numberCopied[parent1[i]] && !numberCopied[parent2[i]]) {
+          child[i] = (random.NextDouble() < 0.5) ? parent1[i] : parent2[i];
+        } else if (!numberCopied[parent1[i]]) {
+          child[i] = parent1[i];
+        } else if (!numberCopied[parent2[i]]) {
+          child[i] = parent2[i];
+        } else {
+          copied = false;
+          unoccupied.Add(i);
+        }
+        if (copied) numberCopied[child[i]] = true;
+      }
+
+      if (unoccupied.Count > 0) {
+        for (int i = 0; i < length; i++) {
+          if (!numberCopied[i]) {
+            int r = random.Next(unoccupied.Count);
+            child[unoccupied[r]] = i;
+            unoccupied.RemoveAt(r);
+          }
+          if (unoccupied.Count == 0) break;
+        }
+      }
+
+      return new Permutation(parent1.PermutationType, child);
+    }
+
+    protected override Permutation Cross(IRandom random, ItemArray<Permutation> parents) {
+      if (parents.Length != 2) throw new InvalidOperationException("UniformLikeCrossover: The number of parents is not equal to 2.");
+      return Apply(random, parents[0], parents[1]);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/HeuristicLab.Encodings.PermutationEncoding-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/HeuristicLab.Encodings.PermutationEncoding-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/HeuristicLab.Encodings.PermutationEncoding-3.3.csproj	(revision 6342)
@@ -118,4 +118,5 @@
     <Compile Include="Crossovers\PartiallyMatchedCrossover.cs" />
     <Compile Include="Crossovers\PositionBasedCrossover.cs" />
+    <Compile Include="Crossovers\UniformLikeCrossover.cs" />
     <Compile Include="HeuristicLabEncodingsPermutationEncodingPlugin.cs" />
     <Compile Include="Interfaces\IPermutationMultiNeighborhoodShakingOperator.cs" />
@@ -179,4 +180,5 @@
     <Compile Include="Moves\TwoOpt\StochasticInversionMultiMoveGenerator.cs" />
     <Compile Include="Moves\TwoOpt\StochasticInversionSingleMoveGenerator.cs" />
+    <Compile Include="PermutationEqualityComparer.cs" />
     <Compile Include="PermutationManipulator.cs" />
     <Compile Include="PermutationCrossover.cs" />
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/ExhaustiveSwap2MoveGenerator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/ExhaustiveSwap2MoveGenerator.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/Swap2/ExhaustiveSwap2MoveGenerator.cs	(revision 6342)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -39,15 +40,22 @@
     }
 
+    public static IEnumerable<Swap2Move> Generate(Permutation permutation) {
+      int length = permutation.Length;
+      if (length == 1) throw new ArgumentException("ExhaustiveSwap2MoveGenerator: There cannot be an Swap move given a permutation of length 1.", "permutation");
+
+      for (int i = 0; i < length - 1; i++)
+        for (int j = i + 1; j < length; j++) {
+          yield return new Swap2Move(i, j);
+        }
+    }
+
     public static Swap2Move[] Apply(Permutation permutation) {
       int length = permutation.Length;
-      if (length == 1) throw new ArgumentException("ExhaustiveSwap2MoveGenerator: There cannot be an Swap move given a permutation of length 1.", "permutation");
       int totalMoves = (length) * (length - 1) / 2;
       Swap2Move[] moves = new Swap2Move[totalMoves];
       int count = 0;
-
-      for (int i = 0; i < length - 1; i++)
-        for (int j = i + 1; j < length; j++) {
-          moves[count++] = new Swap2Move(i, j);
-        }
+      foreach (Swap2Move move in Generate(permutation)) {
+        moves[count++] = move;
+      }
       return moves;
     }
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationEqualityComparer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationEqualityComparer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/PermutationEqualityComparer.cs	(revision 6342)
@@ -0,0 +1,73 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Encodings.PermutationEncoding {
+  [NonDiscoverableType]
+  public class PermutationEqualityComparer : IEqualityComparer<Permutation> {
+    public bool Equals(Permutation x, Permutation y) {
+      if (x.PermutationType != y.PermutationType) return false;
+      if (x.Length != y.Length) return false;
+      switch (x.PermutationType) {
+        case PermutationTypes.Absolute:
+          return EqualsAbsolute(x, y);
+        case PermutationTypes.RelativeDirected:
+          return EqualsRelative(x, y, true);
+        case PermutationTypes.RelativeUndirected:
+          return EqualsRelative(x, y, false);
+        default:
+          throw new InvalidOperationException("unknown permutation type");
+      }
+    }
+
+    private bool EqualsAbsolute(Permutation x, Permutation y) {
+      for (int i = 0; i < x.Length; i++)
+        if (x[i] != y[i]) return false;
+      return true;
+    }
+
+    private bool EqualsRelative(Permutation x, Permutation y, bool directed) {
+      int[] edgesX = CalculateEdgesVector(x);
+      int[] edgesY = CalculateEdgesVector(y);
+      for (int i = 0; i < x.Length; i++)
+        if ((edgesX[i] != edgesY[i]) && (directed || edgesX[edgesY[i]] != i))
+          return false;
+      return true;
+    }
+
+    private int[] CalculateEdgesVector(Permutation permutation) {
+      // transform path representation into adjacency representation
+      int[] edgesVector = new int[permutation.Length];
+      for (int i = 0; i < permutation.Length - 1; i++)
+        edgesVector[permutation[i]] = permutation[i + 1];
+      edgesVector[permutation[permutation.Length - 1]] = permutation[0];
+      return edgesVector;
+    }
+
+    public int GetHashCode(Permutation obj) {
+      if (obj == null) return 0;
+      return obj.GetHashCode();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Tests/HeuristicLab.Encodings.PermutationEncoding-3.3.Tests.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Tests/HeuristicLab.Encodings.PermutationEncoding-3.3.Tests.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Tests/HeuristicLab.Encodings.PermutationEncoding-3.3.Tests.csproj	(revision 6342)
@@ -120,4 +120,5 @@
     <Compile Include="TranslocationInversionManipulatorTest.cs" />
     <Compile Include="TranslocationManipulatorTest.cs" />
+    <Compile Include="UniformLikeCrossoverTest.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -129,4 +130,8 @@
       <Name>HeuristicLab.Collections-3.3</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
+      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
+      <Name>HeuristicLab.Common.Resources-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\..\HeuristicLab.Common\3.3\HeuristicLab.Common-3.3.csproj">
       <Project>{A9AD58B9-3EF9-4CC1-97E5-8D909039FF5C}</Project>
@@ -144,4 +149,8 @@
       <Project>{23DA7FF4-D5B8-41B6-AA96-F0561D24F3EE}</Project>
       <Name>HeuristicLab.Operators-3.3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\HeuristicLab.Optimization.Operators\3.3\HeuristicLab.Optimization.Operators-3.3.csproj">
+      <Project>{25087811-F74C-4128-BC86-8324271DA13E}</Project>
+      <Name>HeuristicLab.Optimization.Operators-3.3</Name>
     </ProjectReference>
     <ProjectReference Include="..\..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
Index: /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Tests/UniformLikeCrossoverTest.cs
===================================================================
--- /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Tests/UniformLikeCrossoverTest.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Tests/UniformLikeCrossoverTest.cs	(revision 6342)
@@ -0,0 +1,103 @@
+﻿using HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace HeuristicLab.Encodings.PermutationEncoding_33.Tests {
+
+
+  /// <summary>
+  ///This is a test class for UniformLikeCrossoverTest and is intended
+  ///to contain all UniformLikeCrossoverTest Unit Tests
+  ///</summary>
+  [TestClass()]
+  public class UniformLikeCrossoverTest {
+
+
+    private TestContext testContextInstance;
+
+    /// <summary>
+    ///Gets or sets the test context which provides
+    ///information about and functionality for the current test run.
+    ///</summary>
+    public TestContext TestContext {
+      get {
+        return testContextInstance;
+      }
+      set {
+        testContextInstance = value;
+      }
+    }
+
+    #region Additional test attributes
+    // 
+    //You can use the following additional attributes as you write your tests:
+    //
+    //Use ClassInitialize to run code before running the first test in the class
+    //[ClassInitialize()]
+    //public static void MyClassInitialize(TestContext testContext)
+    //{
+    //}
+    //
+    //Use ClassCleanup to run code after all tests in a class have run
+    //[ClassCleanup()]
+    //public static void MyClassCleanup()
+    //{
+    //}
+    //
+    //Use TestInitialize to run code before running each test
+    //[TestInitialize()]
+    //public void MyTestInitialize()
+    //{
+    //}
+    //
+    //Use TestCleanup to run code after each test has run
+    //[TestCleanup()]
+    //public void MyTestCleanup()
+    //{
+    //}
+    //
+    #endregion
+
+
+    /// <summary>
+    ///A test for Apply
+    ///</summary>
+    [TestMethod()]
+    public void UniformLikeCrossoverApplyTest() {
+      // test from the paper
+      IRandom random = new TestRandom(new int[] { 0 }, new double[] { 0.2, 0.7, 0.2, 0.2 }); // TODO: Initialize to an appropriate value
+      Permutation parent1 = new Permutation(PermutationTypes.Absolute,
+        new int[] { 3, 2, 0, 7, 5, 4, 1, 6 });
+      Assert.IsTrue(parent1.Validate());
+      Permutation parent2 = new Permutation(PermutationTypes.Absolute,
+        new int[] { 5, 0, 4, 7, 1, 3, 2, 6 });
+      Assert.IsTrue(parent2.Validate());
+      Permutation expected = new Permutation(PermutationTypes.Absolute,
+        new int[] { 3, 0, 4, 7, 5, 2, 1, 6 });
+      Assert.IsTrue(expected.Validate());
+      Permutation actual;
+      actual = UniformLikeCrossover.Apply(random, parent1, parent2);
+      Assert.IsTrue(actual.Validate());
+      Assert.IsTrue(Auxiliary.PermutationIsEqualByPosition(expected, actual));
+    }
+
+    /// <summary>
+    ///A test for Cross
+    ///</summary>
+    [TestMethod()]
+    [DeploymentItem("HeuristicLab.Encodings.PermutationEncoding-3.3.dll")]
+    public void UniformLikeCrossoverCrossTest() {
+      UniformLikeCrossover_Accessor target = new UniformLikeCrossover_Accessor();
+      IRandom random = new TestRandom(new int[] { }, new double[] { 0.1, 0.2, 0.3, 0.4 });
+      random.Reset();
+      bool exceptionFired = false;
+      try {
+        target.Cross(random, new ItemArray<Permutation>(new Permutation[] { 
+          new Permutation(PermutationTypes.RelativeUndirected, 4), new Permutation(PermutationTypes.RelativeUndirected, 4), new Permutation(PermutationTypes.RelativeUndirected, 4)}));
+      } catch (System.InvalidOperationException) {
+        exceptionFired = true;
+      }
+      Assert.IsTrue(exceptionFired);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ViewHost.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ViewHost.Designer.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ViewHost.Designer.cs	(revision 6342)
@@ -51,4 +51,5 @@
       this.viewContextMenuStrip = new HeuristicLab.MainForm.WindowsForms.ViewContextMenuStrip();
       this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+      this.configurationLabel = new System.Windows.Forms.Label();
       this.SuspendLayout();
       // 
@@ -86,4 +87,16 @@
       this.viewContextMenuStrip.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.viewContextMenuStrip_ItemClicked);
       // 
+      // configurationLabel
+      // 
+      this.configurationLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.configurationLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.EditInformation;
+      this.configurationLabel.Location = new System.Drawing.Point(211, 22);
+      this.configurationLabel.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
+      this.configurationLabel.Name = "configurationLabel";
+      this.configurationLabel.Size = new System.Drawing.Size(16, 16);
+      this.configurationLabel.TabIndex = 0;
+      this.configurationLabel.Visible = false;
+      this.configurationLabel.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.configurationLabel_MouseDoubleClick);
+      // 
       // ViewHost
       // 
@@ -91,4 +104,5 @@
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
       this.Controls.Add(this.viewsLabel);
+      this.Controls.Add(this.configurationLabel);
       this.Controls.Add(this.messageLabel);
       this.Name = "ViewHost";
@@ -103,4 +117,5 @@
     private System.Windows.Forms.ToolTip toolTip;
     private HeuristicLab.MainForm.WindowsForms.ViewContextMenuStrip viewContextMenuStrip;
+    private System.Windows.Forms.Label configurationLabel;
 
   }
Index: /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ViewHost.cs
===================================================================
--- /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ViewHost.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.MainForm.WindowsForms/3.3/Controls/ViewHost.cs	(revision 6342)
@@ -101,4 +101,6 @@
             }
           } else viewType = null;
+          configurationLabel.Visible = activeView is IConfigureableView;
+          configurationLabel.Enabled = activeView != null && !activeView.Locked;
         }
       }
@@ -189,4 +191,5 @@
     private void activeView_LockedChanged(object sender, EventArgs e) {
       Locked = activeView.Locked;
+      configurationLabel.Enabled = !activeView.Locked;
     }
 
@@ -200,4 +203,5 @@
       base.OnSizeChanged(e);
       viewsLabel.Location = new Point(Width - viewsLabel.Margin.Right - viewsLabel.Width, viewsLabel.Margin.Top);
+      configurationLabel.Location = new Point(Width - configurationLabel.Margin.Right - configurationLabel.Width, viewsLabel.Bottom + viewsLabel.Margin.Bottom + configurationLabel.Margin.Top);
     }
 
@@ -287,4 +291,8 @@
         startDragAndDrop = false;
     }
+
+    private void configurationLabel_MouseDoubleClick(object sender, MouseEventArgs e) {
+      ((IConfigureableView)ActiveView).ShowConfiguration();
+    }
     #endregion
   }
Index: /trunk/sources/HeuristicLab.MainForm/3.3/HeuristicLab.MainForm-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.MainForm/3.3/HeuristicLab.MainForm-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.MainForm/3.3/HeuristicLab.MainForm-3.3.csproj	(revision 6342)
@@ -12,5 +12,6 @@
     <AssemblyName>HeuristicLab.MainForm-3.3</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
-    <TargetFrameworkProfile></TargetFrameworkProfile>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
     <FileAlignment>512</FileAlignment>
     <SignAssembly>true</SignAssembly>
@@ -111,4 +112,5 @@
   <ItemGroup>
     <None Include="HeuristicLabMainFormPlugin.cs.frame" />
+    <Compile Include="Interfaces\IConfigureableView.cs" />
     <Compile Include="ViewAttribute.cs" />
     <Compile Include="Interfaces\IContentView.cs" />
Index: /trunk/sources/HeuristicLab.MainForm/3.3/Interfaces/IConfigureableView.cs
===================================================================
--- /trunk/sources/HeuristicLab.MainForm/3.3/Interfaces/IConfigureableView.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.MainForm/3.3/Interfaces/IConfigureableView.cs	(revision 6342)
@@ -0,0 +1,6 @@
+﻿
+namespace HeuristicLab.MainForm {
+  public interface IConfigureableView : IView {
+    void ShowConfiguration();
+  }
+}
Index: /trunk/sources/HeuristicLab.Persistence/3.3/Default/Xml/Primitive/System.Drawing/Font2XmlSerializer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Persistence/3.3/Default/Xml/Primitive/System.Drawing/Font2XmlSerializer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Persistence/3.3/Default/Xml/Primitive/System.Drawing/Font2XmlSerializer.cs	(revision 6342)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Drawing;
+
+namespace HeuristicLab.Persistence.Default.Xml.Primitive {
+  internal sealed class Font2XmlSerializer : PrimitiveXmlSerializerBase<Font> {
+
+    public override XmlString Format(Font font) {
+      return new XmlString(string.Format("{0};{1};{2};{3};{4};{5}",
+        font.Name,
+        Float2XmlSerializer.FormatG8(font.Size),
+        font.Style,
+        font.Unit,
+        font.GdiCharSet,
+        font.GdiVerticalFont));
+    }
+
+    public override Font Parse(XmlString fontData) {
+      string[] tokens = fontData.Data.Split(';');
+      return new Font(
+        tokens[0],
+        Float2XmlSerializer.ParseG8(tokens[1]),
+        (FontStyle)Enum.Parse(typeof(FontStyle), tokens[2]),
+        (GraphicsUnit)Enum.Parse(typeof(GraphicsUnit), tokens[3]),
+        byte.Parse(tokens[4]),
+        bool.Parse(tokens[5]));
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj	(revision 6342)
@@ -204,4 +204,5 @@
     <Compile Include="Default\Xml\Primitive\SimpleNumber2XmlSerializerBase.cs" />
     <Compile Include="Default\Xml\Primitive\String2XmlSerializer.cs" />
+    <Compile Include="Default\Xml\Primitive\System.Drawing\Font2XmlSerializer.cs" />
     <Compile Include="Default\Xml\Primitive\TimeSpan2XmlSerializer.cs" />
     <Compile Include="Default\Xml\Primitive\UInt2XmlSerializer.cs" />
Index: /trunk/sources/HeuristicLab.Persistence/3.3/Tests/UseCases.cs
===================================================================
--- /trunk/sources/HeuristicLab.Persistence/3.3/Tests/UseCases.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Persistence/3.3/Tests/UseCases.cs	(revision 6342)
@@ -1198,9 +1198,9 @@
       public OneWayTest() { this.value = "default"; }
       public string value;
-      [Storable(AllowOneWay=true)]
+      [Storable(AllowOneWay = true)]
       public string ReadOnly {
         get { return "ReadOnly"; }
       }
-      [Storable(AllowOneWay=true)]
+      [Storable(AllowOneWay = true)]
       public string WriteOnly {
         set { this.value = value; }
@@ -1255,4 +1255,20 @@
     }
 
+    [TestMethod]
+    public void FontTest() {
+      List<Font> fonts = new List<Font>() {
+        new Font(FontFamily.GenericSansSerif, 12),
+        new Font("Times New Roman", 21, FontStyle.Bold, GraphicsUnit.Pixel),
+        new Font("Courier New", 10, FontStyle.Underline, GraphicsUnit.Document),
+        new Font("Helvetica", 21, FontStyle.Strikeout, GraphicsUnit.Inch, 0, true),
+      };
+      XmlGenerator.Serialize(fonts, tempFile);
+      var newFonts = XmlParser.Deserialize<List<Font>>(tempFile);
+      Assert.AreEqual(fonts[0], newFonts[0]);
+      Assert.AreEqual(fonts[1], newFonts[1]);
+      Assert.AreEqual(fonts[2], newFonts[2]);
+      Assert.AreEqual(fonts[3], newFonts[3]);
+    }
+
 
 
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/HeuristicLab.Problems.QuadraticAssignment.Views-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/HeuristicLab.Problems.QuadraticAssignment.Views-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/HeuristicLab.Problems.QuadraticAssignment.Views-3.3.csproj	(revision 6342)
@@ -102,4 +102,11 @@
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="HeuristicLab.Collections-3.3, Version=3.3.0.0, Culture=neutral, PublicKeyToken=ba48961d6f65dcec, processorArchitecture=x86" />
+    <Reference Include="HeuristicLab.Data.Views-3.3">
+      <HintPath>..\..\HeuristicLab.Data.Views\3.3\bin\x86\Debug\HeuristicLab.Data.Views-3.3.dll</HintPath>
+    </Reference>
+    <Reference Include="HeuristicLab.Visualization.ChartControlsExtensions-3.3">
+      <HintPath>..\..\HeuristicLab.Visualization.ChartControlsExtensions\3.3\bin\x86\Debug\HeuristicLab.Visualization.ChartControlsExtensions-3.3.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -107,4 +114,5 @@
     <Reference Include="System.Drawing" />
     <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Windows.Forms.DataVisualization" />
     <Reference Include="System.Xml" />
   </ItemGroup>
@@ -184,4 +192,8 @@
       <Name>HeuristicLab.MainForm-3.3</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Optimization.Views\3.3\HeuristicLab.Optimization.Views-3.3.csproj">
+      <Project>{662B4B15-8F4D-4AE5-B3EB-D91C215F5AF2}</Project>
+      <Name>HeuristicLab.Optimization.Views-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Optimization\3.3\HeuristicLab.Optimization-3.3.csproj">
       <Project>{14AB8D24-25BC-400C-A846-4627AA945192}</Project>
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.Designer.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.Designer.cs	(revision 6342)
@@ -101,4 +101,6 @@
       this.QAPLIBInstancesLabel.AutoSize = true;
       this.QAPLIBInstancesLabel.Cursor = System.Windows.Forms.Cursors.Hand;
+      this.QAPLIBInstancesLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      this.QAPLIBInstancesLabel.ForeColor = System.Drawing.Color.Blue;
       this.QAPLIBInstancesLabel.Location = new System.Drawing.Point(3, 5);
       this.QAPLIBInstancesLabel.Name = "QAPLIBInstancesLabel";
@@ -109,4 +111,6 @@
               "qaplib/");
       this.QAPLIBInstancesLabel.Click += new System.EventHandler(this.QAPLIBInstancesLabel_Click);
+      this.QAPLIBInstancesLabel.MouseEnter += new System.EventHandler(this.QAPLIBInstancesLabel_MouseEnter);
+      this.QAPLIBInstancesLabel.MouseLeave += new System.EventHandler(this.QAPLIBInstancesLabel_MouseLeave);
       // 
       // instancesComboBox
@@ -191,8 +195,4 @@
       this.Name = "QuadraticAssignmentProblemView";
       this.Size = new System.Drawing.Size(647, 492);
-      this.Controls.SetChildIndex(this.infoLabel, 0);
-      this.Controls.SetChildIndex(this.parameterCollectionView, 0);
-      this.Controls.SetChildIndex(this.nameLabel, 0);
-      this.Controls.SetChildIndex(this.nameTextBox, 0);
       this.Controls.SetChildIndex(this.QAPLIBInstancesLabel, 0);
       this.Controls.SetChildIndex(this.loadInstanceButton, 0);
@@ -200,4 +200,8 @@
       this.Controls.SetChildIndex(this.tabControl, 0);
       this.Controls.SetChildIndex(this.instancesComboBox, 0);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      this.Controls.SetChildIndex(this.parameterCollectionView, 0);
+      this.Controls.SetChildIndex(this.nameLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
       this.tabControl.ResumeLayout(false);
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.cs	(revision 6342)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Drawing;
 using System.Windows.Forms;
 using HeuristicLab.Common.Resources;
@@ -120,4 +121,16 @@
       System.Diagnostics.Process.Start("http://www.seas.upenn.edu/qaplib/");
     }
+
+    private void QAPLIBInstancesLabel_MouseEnter(object sender, EventArgs e) {
+      Cursor = Cursors.Hand;
+      QAPLIBInstancesLabel.ForeColor = Color.Red;
+      toolTip.SetToolTip(QAPLIBInstancesLabel, "Browse to http://www.seas.upenn.edu/qaplib/");
+    }
+
+    private void QAPLIBInstancesLabel_MouseLeave(object sender, EventArgs e) {
+      Cursor = Cursors.Default;
+      QAPLIBInstancesLabel.ForeColor = Color.Blue;
+      toolTip.SetToolTip(QAPLIBInstancesLabel, String.Empty);
+    }
   }
 }
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.resx
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.resx	(revision 6341)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment.Views/3.3/QuadraticAssignmentProblemView.resx	(revision 6342)
@@ -121,4 +121,7 @@
     <value>107, 17</value>
   </metadata>
+  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>107, 17</value>
+  </metadata>
   <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>17, 17</value>
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/BestQAPSolutionAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/BestQAPSolutionAnalyzer.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/BestQAPSolutionAnalyzer.cs	(revision 6342)
@@ -61,4 +61,7 @@
       get { return (LookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
     }
+    public LookupParameter<ItemList<Permutation>> BestKnownSolutionsParameter {
+      get { return (LookupParameter<ItemList<Permutation>>)Parameters["BestKnownSolutions"]; }
+    }
     public LookupParameter<Permutation> BestKnownSolutionParameter {
       get { return (LookupParameter<Permutation>)Parameters["BestKnownSolution"]; }
@@ -81,5 +84,16 @@
       Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the best QAP solution should be stored."));
       Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this QAP instance."));
+      Parameters.Add(new LookupParameter<ItemList<Permutation>>("BestKnownSolutions", "The best known solutions (there may be multiple) of this QAP instance."));
       Parameters.Add(new LookupParameter<Permutation>("BestKnownSolution", "The best known solution of this QAP instance."));
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (!Parameters.ContainsKey("BestKnownSolutions")) {
+        Parameters.Add(new LookupParameter<ItemList<Permutation>>("BestKnownSolutions", "The best known solutions of this QAP instance."));
+      }
+      #endregion
     }
 
@@ -93,14 +107,38 @@
       DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue;
 
-      int i = -1;
-      if (!max)
-        i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index;
-      else i = qualities.Select((x, index) => new { index, x.Value }).OrderByDescending(x => x.Value).First().index;
+      var sorted = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).ToArray();
+      if (max) sorted = sorted.Reverse().ToArray();
+      int i = sorted.First().index;
 
-      if (bestKnownQuality == null ||
-          max && qualities[i].Value > bestKnownQuality.Value ||
-          !max && qualities[i].Value < bestKnownQuality.Value) {
+      if (bestKnownQuality == null
+          || max && qualities[i].Value > bestKnownQuality.Value
+          || !max && qualities[i].Value < bestKnownQuality.Value) {
+        // if there isn't a best-known quality or we improved the best-known quality we'll add the current solution as best-known
         BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[i].Value);
         BestKnownSolutionParameter.ActualValue = (Permutation)permutations[i].Clone();
+        BestKnownSolutionsParameter.ActualValue = new ItemList<Permutation>();
+        BestKnownSolutionsParameter.ActualValue.Add((Permutation)permutations[i].Clone());
+      } else if (bestKnownQuality.Value == qualities[i].Value) {
+        // if we matched the best-known quality we'll try to set the best-known solution if it isn't null
+        // and try to add it to the pool of best solutions if it is different
+        if (BestKnownSolutionParameter.ActualValue == null)
+          BestKnownSolutionParameter.ActualValue = (Permutation)permutations[i].Clone();
+        if (BestKnownSolutionsParameter.ActualValue == null)
+          BestKnownSolutionsParameter.ActualValue = new ItemList<Permutation>();
+        PermutationEqualityComparer comparer = new PermutationEqualityComparer();
+        foreach (var k in sorted) { // for each solution that we found check if it is in the pool of best-knowns
+          if (!max && k.Value > qualities[i].Value
+            || max && k.Value < qualities[i].Value) break; // stop when we reached a solution worse than the best-known quality
+          Permutation p = permutations[k.index];
+          bool alreadyPresent = false;
+          foreach (Permutation p2 in BestKnownSolutionsParameter.ActualValue) {
+            if (comparer.Equals(p, p2)) {
+              alreadyPresent = true;
+              break;
+            }
+          }
+          if (!alreadyPresent)
+            BestKnownSolutionsParameter.ActualValue.Add((Permutation)permutations[k.index].Clone());
+        }
       }
 
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPAlleleFrequencyAnalyzer.cs	(revision 6342)
@@ -0,0 +1,76 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  /// <summary>
+  /// An operator for analyzing the frequency of alleles in solutions of Quadratic Assignment Problems.
+  /// </summary>
+  [Item("QAPAlleleFrequencyAnalyzer", "An operator for analyzing the frequency of alleles in solutions of Quadratic Assignment Problems.")]
+  [StorableClass]
+  public sealed class QAPAlleleFrequencyAnalyzer : AlleleFrequencyAnalyzer<Permutation> {
+    public LookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+    public LookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (LookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+
+    [StorableConstructor]
+    private QAPAlleleFrequencyAnalyzer(bool deserializing) : base(deserializing) { }
+    private QAPAlleleFrequencyAnalyzer(QAPAlleleFrequencyAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public QAPAlleleFrequencyAnalyzer()
+      : base() {
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The matrix contains the weights between the facilities."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The matrix which contains the distances between the locations."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPAlleleFrequencyAnalyzer(this, cloner);
+    }
+
+    protected override Allele[] CalculateAlleles(Permutation solution) {
+      Allele[] alleles = new Allele[solution.Length];
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+      int source, target;
+      double impact;
+
+      for (int i = 0; i < solution.Length; i++) {
+        source = i;
+        target = solution[i];
+        impact = 0;
+        for (int j = 0; j < solution.Length; j++)
+          impact += weights[source, j] * distances[target, solution[j]];
+        alleles[i] = new Allele(source.ToString() + "->" + target.ToString(), impact);
+      }
+
+      return alleles;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Analyzers/QAPPopulationDiversityAnalyzer.cs	(revision 6342)
@@ -0,0 +1,67 @@
+#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  /// <summary>
+  /// An operator for analyzing the diversity of solutions of Quadratic Assignment Problems regarding their structural identity (number of equal facilty->location assignments).
+  /// </summary>
+  [Item("QAPPopulationDiversityAnalyzer", "An operator for analyzing the diversity of solutions of Quadratic Assignment Problems regarding their structural identity (number of equal facilty->location assignments).")]
+  [StorableClass]
+  public sealed class QAPPopulationDiversityAnalyzer : PopulationDiversityAnalyzer<Permutation> {
+    [StorableConstructor]
+    private QAPPopulationDiversityAnalyzer(bool deserializing) : base(deserializing) { }
+    private QAPPopulationDiversityAnalyzer(QAPPopulationDiversityAnalyzer original, Cloner cloner) : base(original, cloner) { }
+    public QAPPopulationDiversityAnalyzer() : base() { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPPopulationDiversityAnalyzer(this, cloner);
+    }
+
+    protected override double[,] CalculateSimilarities(Permutation[] solutions) {
+      int count = solutions.Length;
+      double[,] similarities = new double[count, count];
+
+      for (int i = 0; i < count; i++) {
+        similarities[i, i] = 1;
+        for (int j = i + 1; j < count; j++) {
+          similarities[i, j] = CalculateSimilarity(solutions[i], solutions[j]);
+          similarities[j, i] = similarities[i, j];
+        }
+      }
+      return similarities;
+    }
+
+    private double CalculateSimilarity(Permutation assignment1, Permutation assignment2) {
+      int identicalAssignments = 0;
+      for (int i = 0; i < assignment1.Length; i++) {
+        if (assignment1[i] == assignment2[i])
+          identicalAssignments++;
+      }
+      return ((double)identicalAssignments) / assignment1.Length;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Data/esc32a.sln
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Data/esc32a.sln	(revision 6342)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Data/esc32a.sln	(revision 6342)
@@ -0,0 +1,2 @@
+ 32 130
+ 26 18 20 24 22 30 28 11 21 5 29 10 25 17 19 12 13 23 31 32 3 14 4 7 16 9 15 6 8 1 27 2
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Data/sko49.sln
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Data/sko49.sln	(revision 6342)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Data/sko49.sln	(revision 6342)
@@ -0,0 +1,4 @@
+ 49 23386
+ 47 36 26 25 28 46 49 13 7 42 20 18 11 40 14 41 35 43 29 48
+ 12 24 9 10 6 34 2 31 1 15 45 27 38 23 3 19 32 37 33 30 8 22
+ 4 17 21 5 16 39 44
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPEvaluator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPEvaluator.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/Evaluators/QAPEvaluator.cs	(revision 6342)
@@ -69,4 +69,13 @@
     }
 
+    public static double Impact(int facility, Permutation assignment, DoubleMatrix weights, DoubleMatrix distances) {
+      double impact = 0;
+      for (int i = 0; i < assignment.Length; i++) {
+        impact += weights[facility, i] * distances[assignment[facility], assignment[i]];
+        impact += weights[i, facility] * distances[assignment[i], assignment[facility]];
+      }
+      return impact;
+    }
+
     public override IOperation Apply() {
       Permutation assignment = PermutationParameter.ActualValue;
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/HeuristicLab.Problems.QuadraticAssignment-3.3.csproj	(revision 6342)
@@ -109,4 +109,6 @@
   <ItemGroup>
     <Compile Include="Analyzers\BestQAPSolutionAnalyzer.cs" />
+    <Compile Include="Analyzers\QAPAlleleFrequencyAnalyzer.cs" />
+    <Compile Include="Analyzers\QAPPopulationDiversityAnalyzer.cs" />
     <Compile Include="Evaluators\QAPSwap2MoveEvaluator.cs" />
     <Compile Include="Evaluators\QAPEvaluator.cs" />
@@ -118,4 +120,5 @@
     <Compile Include="Interfaces\IQAPEvaluator.cs" />
     <Compile Include="Interfaces\IQAPMoveEvaluator.cs" />
+    <Compile Include="LocalImprovement\QAPExhaustiveSwap2LocalImprovement.cs" />
     <Compile Include="Parsers\QAPLIBSolutionParser.cs" />
     <Compile Include="Parsers\QAPLIBParser.cs" />
@@ -386,4 +389,8 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Analysis\3.3\HeuristicLab.Analysis-3.3.csproj">
+      <Project>{887425B4-4348-49ED-A457-B7D2C26DDBF9}</Project>
+      <Name>HeuristicLab.Analysis-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Collections\3.3\HeuristicLab.Collections-3.3.csproj">
       <Project>{958B43BC-CC5C-4FA2-8628-2B3B01D890B6}</Project>
@@ -432,7 +439,13 @@
   </ItemGroup>
   <ItemGroup>
-    <Content Include="Data\tai100a.sln" />
-    <Content Include="Data\tai25a.sln" />
-    <Content Include="Data\tai50a.sln" />
+    <EmbeddedResource Include="Data\tai100a.sln" />
+    <EmbeddedResource Include="Data\tai25a.sln" />
+    <EmbeddedResource Include="Data\tai50a.sln" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Data\esc32a.sln" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Data\sko49.sln" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveSwap2LocalImprovement.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveSwap2LocalImprovement.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/LocalImprovement/QAPExhaustiveSwap2LocalImprovement.cs	(revision 6342)
@@ -0,0 +1,132 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Encodings.PermutationEncoding;
+using HeuristicLab.Operators;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Problems.QuadraticAssignment {
+  [Item("QAPExhaustiveSwap2LocalImprovement", "Takes a solution and finds the local optimum with respect to the swap2 neighborhood by decending along the steepest gradient.")]
+  [StorableClass]
+  public class QAPExhaustiveSwap2LocalImprovement : SingleSuccessorOperator, ILocalImprovementOperator {
+
+    public Type ProblemType {
+      get { return typeof(QuadraticAssignmentProblem); }
+    }
+
+    [Storable]
+    private QuadraticAssignmentProblem problem;
+    public IProblem Problem {
+      get { return problem; }
+      set { problem = (QuadraticAssignmentProblem)value; }
+    }
+
+    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
+      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
+    }
+
+    public ILookupParameter<IntValue> EvaluatedSolutionsParameter {
+      get { return (ILookupParameter<IntValue>)Parameters["EvaluatedSolutions"]; }
+    }
+
+    public ILookupParameter<ResultCollection> ResultsParameter {
+      get { return (ILookupParameter<ResultCollection>)Parameters["Results"]; }
+    }
+
+    public ILookupParameter<Permutation> AssignmentParameter {
+      get { return (ILookupParameter<Permutation>)Parameters["Assignment"]; }
+    }
+
+    public ILookupParameter<DoubleValue> QualityParameter {
+      get { return (ILookupParameter<DoubleValue>)Parameters["Quality"]; }
+    }
+
+    public ILookupParameter<BoolValue> MaximizationParameter {
+      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> WeightsParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Weights"]; }
+    }
+
+    public ILookupParameter<DoubleMatrix> DistancesParameter {
+      get { return (ILookupParameter<DoubleMatrix>)Parameters["Distances"]; }
+    }
+
+    [StorableConstructor]
+    protected QAPExhaustiveSwap2LocalImprovement(bool deserializing) : base(deserializing) { }
+    protected QAPExhaustiveSwap2LocalImprovement(QAPExhaustiveSwap2LocalImprovement original, Cloner cloner)
+      : base(original, cloner) {
+      this.problem = cloner.Clone(original.problem);
+    }
+    public QAPExhaustiveSwap2LocalImprovement()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum amount of iterations that should be performed (note that this operator will abort earlier when a local optimum is reached.", new IntValue(10000)));
+      Parameters.Add(new LookupParameter<IntValue>("EvaluatedSolutions", "The amount of evaluated solutions (here a move is counted only as 4/n evaluated solutions with n being the length of the permutation)."));
+      Parameters.Add(new LookupParameter<ResultCollection>("Results", "The collection where to store results."));
+      Parameters.Add(new LookupParameter<Permutation>("Assignment", "The permutation that is to be locally optimized."));
+      Parameters.Add(new LookupParameter<DoubleValue>("Quality", "The quality value of the assignment."));
+      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem should be maximized or minimized."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Weights", "The weights matrix."));
+      Parameters.Add(new LookupParameter<DoubleMatrix>("Distances", "The distances matrix."));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new QAPExhaustiveSwap2LocalImprovement(this, cloner);
+    }
+
+    public override IOperation Apply() {
+      int maxIterations = MaximumIterationsParameter.ActualValue.Value;
+      Permutation assignment = AssignmentParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      DoubleMatrix weights = WeightsParameter.ActualValue;
+      DoubleMatrix distances = DistancesParameter.ActualValue;
+
+      double evaluatedSolutions = 0.0;
+      double evalSolPerMove = 4.0 / assignment.Length;
+
+      for (int i = 0; i < maxIterations; i++) {
+        Swap2Move bestMove = null;
+        double bestQuality = 0; // we have to make an improvement, so 0 is the baseline
+        foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(assignment)) {
+          double moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, weights, distances);
+          evaluatedSolutions += evalSolPerMove;
+          if (maximization && moveQuality > bestQuality
+            || !maximization && moveQuality < bestQuality) {
+            bestQuality = moveQuality;
+            bestMove = move;
+          }
+        }
+        if (bestMove == null) break;
+        Swap2Manipulator.Apply(assignment, bestMove.Index1, bestMove.Index2);
+        QualityParameter.ActualValue.Value += bestQuality;
+      }
+      EvaluatedSolutionsParameter.ActualValue.Value += (int)Math.Ceiling(evaluatedSolutions);
+      return base.Apply();
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Problems.QuadraticAssignment/3.3/QuadraticAssignmentProblem.cs	(revision 6342)
@@ -49,4 +49,7 @@
 
     #region Parameter Properties
+    public IValueParameter<ItemList<Permutation>> BestKnownSolutionsParameter {
+      get { return (IValueParameter<ItemList<Permutation>>)Parameters["BestKnownSolutions"]; }
+    }
     public IValueParameter<Permutation> BestKnownSolutionParameter {
       get { return (IValueParameter<Permutation>)Parameters["BestKnownSolution"]; }
@@ -61,4 +64,8 @@
 
     #region Properties
+    public ItemList<Permutation> BestKnownSolutions {
+      get { return BestKnownSolutionsParameter.Value; }
+      set { BestKnownSolutionsParameter.Value = value; }
+    }
     public Permutation BestKnownSolution {
       get { return BestKnownSolutionParameter.Value; }
@@ -88,4 +95,12 @@
       get { return Operators.OfType<BestQAPSolutionAnalyzer>().FirstOrDefault(); }
     }
+
+    private QAPAlleleFrequencyAnalyzer QAPAlleleFrequencyAnalyzer {
+      get { return Operators.OfType<QAPAlleleFrequencyAnalyzer>().FirstOrDefault(); }
+    }
+
+    private QAPPopulationDiversityAnalyzer QAPPopulationDiversityAnalyzer {
+      get { return Operators.OfType<QAPPopulationDiversityAnalyzer>().FirstOrDefault(); }
+    }
     #endregion
 
@@ -98,4 +113,5 @@
     public QuadraticAssignmentProblem()
       : base(new QAPEvaluator(), new RandomPermutationCreator()) {
+      Parameters.Add(new OptionalValueParameter<ItemList<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
       Parameters.Add(new OptionalValueParameter<Permutation>("BestKnownSolution", "The best known solution which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
       Parameters.Add(new ValueParameter<DoubleMatrix>("Weights", "The strength of the connection between the facilities.", new DoubleMatrix(5, 5)));
@@ -130,4 +146,29 @@
     public override IDeepCloneable Clone(Cloner cloner) {
       return new QuadraticAssignmentProblem(this, cloner);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      /*if (Parameters.ContainsKey("BestKnownSolution")) {
+        Permutation solution = ((IValueParameter<Permutation>)Parameters["BestKnownSolution"]).Value;
+        Parameters.Remove("BestKnownSolution");
+        Parameters.Add(new OptionalValueParameter<ItemList<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
+        if (solution != null) {
+          BestKnownSolutions = new ItemList<Permutation>();
+          BestKnownSolutions.Add(solution);
+        }
+      }*/
+      if (!Parameters.ContainsKey("BestKnownSolutions")) {
+        Parameters.Add(new OptionalValueParameter<ItemList<Permutation>>("BestKnownSolutions", "The list of best known solutions which is updated whenever a new better solution is found or may be the optimal solution if it is known beforehand.", null));
+      }
+      if (Parameters.ContainsKey("DistanceMatrix")) {
+        DoubleMatrix bla = ((ValueParameter<DoubleMatrix>)Parameters["DistanceMatrix"]).Value;
+        Parameters.Remove("DistanceMatrix");
+        Parameters.Add(new ValueParameter<DoubleMatrix>("Distances", "bla", bla));
+      }
+      AttachEventHandlers();
+      #endregion
     }
 
@@ -217,9 +258,4 @@
 
     #region Helpers
-    [StorableHook(HookType.AfterDeserialization)]
-    private void AfterDeserializationHook() {
-      AttachEventHandlers();
-    }
-
     private void AttachEventHandlers() {
       SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
@@ -238,4 +274,7 @@
       Operators.AddRange(ApplicationManager.Manager.GetInstances<IQAPMoveEvaluator>());
       Operators.Add(new BestQAPSolutionAnalyzer());
+      Operators.Add(new QAPAlleleFrequencyAnalyzer());
+      Operators.Add(new QAPPopulationDiversityAnalyzer());
+      Operators.Add(new QAPExhaustiveSwap2LocalImprovement());
       ParameterizeAnalyzers();
       ParameterizeOperators();
@@ -262,6 +301,21 @@
         BestQAPSolutionAnalyzer.ResultsParameter.ActualName = "Results";
         BestQAPSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
-        BestQAPSolutionAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
+        BestQAPSolutionAnalyzer.BestKnownSolutionsParameter.ActualName = BestKnownSolutionsParameter.Name;
         BestQAPSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+      }
+      if (QAPAlleleFrequencyAnalyzer != null) {
+        QAPAlleleFrequencyAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        QAPAlleleFrequencyAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
+        QAPAlleleFrequencyAnalyzer.DistancesParameter.ActualName = DistancesParameter.Name;
+        QAPAlleleFrequencyAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+        QAPAlleleFrequencyAnalyzer.ResultsParameter.ActualName = "Results";
+        QAPAlleleFrequencyAnalyzer.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+        QAPAlleleFrequencyAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
+      }
+      if (QAPPopulationDiversityAnalyzer != null) {
+        QAPPopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
+        QAPPopulationDiversityAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        QAPPopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
+        QAPPopulationDiversityAnalyzer.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
       }
     }
@@ -291,4 +345,13 @@
       foreach (var op in Operators.OfType<IPermutationMultiNeighborhoodShakingOperator>())
         op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+
+      QAPExhaustiveSwap2LocalImprovement localOpt = Operators.OfType<QAPExhaustiveSwap2LocalImprovement>().SingleOrDefault();
+      if (localOpt != null) {
+        localOpt.AssignmentParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
+        localOpt.DistancesParameter.ActualName = DistancesParameter.Name;
+        localOpt.MaximizationParameter.ActualName = MaximizationParameter.Name;
+        localOpt.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
+        localOpt.WeightsParameter.ActualName = WeightsParameter.Name;
+      }
     }
 
@@ -315,5 +378,5 @@
       Description = "Imported problem data using QAPLIBParser " + Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyFileVersionAttribute), true).Cast<AssemblyFileVersionAttribute>().FirstOrDefault().Version + ".";
       BestKnownQuality = null;
-      BestKnownSolution = null;
+      BestKnownSolutions = null;
       OnReset();
     }
@@ -348,11 +411,14 @@
             if (solParser.Quality.IsAlmost(QAPEvaluator.Apply(new Permutation(PermutationTypes.Absolute, solParser.Assignment), Weights, Distances))) {
               BestKnownQuality = new DoubleValue(solParser.Quality);
+              BestKnownSolutions = new ItemList<Permutation>(new Permutation[] { new Permutation(PermutationTypes.Absolute, solParser.Assignment) });
               BestKnownSolution = new Permutation(PermutationTypes.Absolute, solParser.Assignment);
             } else {
               BestKnownQuality = new DoubleValue(solParser.Quality);
+              BestKnownSolutions = null;
               BestKnownSolution = null;
             }
           } else {
             BestKnownQuality = new DoubleValue(solParser.Quality);
+            BestKnownSolutions = new ItemList<Permutation>(new Permutation[] { new Permutation(PermutationTypes.Absolute, solParser.Assignment) });
             BestKnownSolution = new Permutation(PermutationTypes.Absolute, solParser.Assignment);
           }
@@ -360,4 +426,5 @@
       } else {
         BestKnownQuality = null;
+        BestKnownSolutions = null;
         BestKnownSolution = null;
       }
Index: /trunk/sources/HeuristicLab.Selection/3.3/GeneralizedRankSelector.cs
===================================================================
--- /trunk/sources/HeuristicLab.Selection/3.3/GeneralizedRankSelector.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Selection/3.3/GeneralizedRankSelector.cs	(revision 6342)
@@ -0,0 +1,84 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Optimization;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Selection {
+  /// <summary>
+  /// The generalized rank selection operator selects qualities by rank with a varying focus on better qualities. It is implemented as described in Tate, D. M. and Smith, A. E. 1995. A genetic approach to the quadratic assignment problem. Computers & Operations Research, vol. 22, pp. 73-83.
+  /// </summary>
+  [Item("GeneralizedRankSelector", "The generalized rank selection operator selects qualities by rank with a varying focus on better qualities. It is implemented as described in Tate, D. M. and Smith, A. E. 1995. A genetic approach to the quadratic assignment problem. Computers & Operations Research, vol. 22, pp. 73-83.")]
+  [StorableClass]
+  public sealed class GeneralizedRankSelector : StochasticSingleObjectiveSelector, ISelector {
+
+    public IValueLookupParameter<DoubleValue> PressureParameter {
+      get { return (IValueLookupParameter<DoubleValue>)Parameters["Pressure"]; }
+    }
+
+    [StorableConstructor]
+    private GeneralizedRankSelector(bool deserializing) : base(deserializing) { }
+    private GeneralizedRankSelector(GeneralizedRankSelector original, Cloner cloner) : base(original, cloner) { }
+    public GeneralizedRankSelector()
+      : base() {
+      Parameters.Add(new ValueLookupParameter<DoubleValue>("Pressure", "The selection pressure that is applied, must lie in the interval [1;infinity). A pressure of 1 equals random selection, higher pressure values focus on selecting better qualities.", new DoubleValue(2)));
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new GeneralizedRankSelector(this, cloner);
+    }
+
+    protected override IScope[] Select(List<IScope> scopes) {
+      int count = NumberOfSelectedSubScopesParameter.ActualValue.Value;
+      bool copy = CopySelectedParameter.Value.Value;
+      IRandom random = RandomParameter.ActualValue;
+      bool maximization = MaximizationParameter.ActualValue.Value;
+      ItemArray<DoubleValue> qualities = QualityParameter.ActualValue;
+      IScope[] selected = new IScope[count];
+      double pressure = PressureParameter.ActualValue.Value;
+
+      var ordered = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).ToList();
+      if (maximization) ordered.Reverse();
+
+      int m = scopes.Count;
+      for (int i = 0; i < count; i++) {
+        double rand = 1 + random.NextDouble() * (Math.Pow(m, 1.0 / pressure) - 1);
+        int selIdx = (int)Math.Floor(Math.Pow(rand, pressure) - 1);
+
+        if (copy) {
+          selected[i] = (IScope)scopes[ordered[selIdx].index].Clone();
+        } else {
+          selected[i] = scopes[ordered[selIdx].index];
+          scopes.Remove(selected[i]);
+          m--;
+        }
+      }
+      return selected;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.Selection/3.3/HeuristicLab.Selection-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Selection/3.3/HeuristicLab.Selection-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Selection/3.3/HeuristicLab.Selection-3.3.csproj	(revision 6342)
@@ -109,4 +109,5 @@
     <Compile Include="ConditionalSelector.cs" />
     <Compile Include="CrowdedTournamentSelector.cs" />
+    <Compile Include="GeneralizedRankSelector.cs" />
     <Compile Include="LeftSelector.cs" />
     <Compile Include="NoSameMatesSelector.cs" />
Index: /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/EnhancedChart.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/EnhancedChart.Designer.cs	(revision 6341)
+++ /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/EnhancedChart.Designer.cs	(revision 6342)
@@ -60,5 +60,5 @@
             this.copyImageToClipboardBitmapToolStripMenuItem});
       this.contextMenuStrip.Name = "contextMenuStrip";
-      this.contextMenuStrip.Size = new System.Drawing.Size(257, 48);
+      this.contextMenuStrip.Size = new System.Drawing.Size(257, 76);
       // 
       // exportChartToolStripMenuItem
@@ -78,6 +78,6 @@
       // saveFileDialog
       // 
-      this.saveFileDialog.Filter = "Bitmap (*.bmp)|*.bmp|JPEG (*.jpg)|*.jpg|EMF (*.emf)|*.emf|PNG (*.png)|*.png|GIF " +
-          "(*.gif)|*.gif|TIFF (*.tif)|*.tif\"";
+      this.saveFileDialog.Filter = "Bitmap (*.bmp)|*.bmp|JPEG (*.jpg)|*.jpg|EMF (*.emf)|*.emf|PNG (*.png)|*.png|GIF (" +
+          "*.gif)|*.gif|TIFF (*.tif)|*.tif\"";
       this.saveFileDialog.FilterIndex = 2;
       // 
Index: /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/EnhancedChart.resx
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/EnhancedChart.resx	(revision 6342)
+++ /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/EnhancedChart.resx	(revision 6342)
@@ -0,0 +1,129 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="contextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>146, 17</value>
+  </metadata>
+  <metadata name="saveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+</root>
Index: /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HeuristicLab.Visualization.ChartControlsExtensions-3.3.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HeuristicLab.Visualization.ChartControlsExtensions-3.3.csproj	(revision 6341)
+++ /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HeuristicLab.Visualization.ChartControlsExtensions-3.3.csproj	(revision 6342)
@@ -122,4 +122,10 @@
     </Compile>
     <Compile Include="HeuristicLabVisualizationChartControlsExtensionsPlugin.cs" />
+    <Compile Include="HistogramControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="HistogramControl.Designer.cs">
+      <DependentUpon>HistogramControl.cs</DependentUpon>
+    </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
@@ -130,8 +136,17 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
+      <Project>{0E27A536-1C4A-4624-A65E-DC4F4F23E3E1}</Project>
+      <Name>HeuristicLab.Common.Resources-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
       <Project>{94186A6A-5176-4402-AE83-886557B53CCA}</Project>
       <Name>HeuristicLab.PluginInfrastructure-3.3</Name>
     </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="EnhancedChart.resx">
+      <DependentUpon>EnhancedChart.cs</DependentUpon>
+    </EmbeddedResource>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Index: /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HeuristicLabVisualizationChartControlsExtensionsPlugin.cs.frame
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HeuristicLabVisualizationChartControlsExtensionsPlugin.cs.frame	(revision 6341)
+++ /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HeuristicLabVisualizationChartControlsExtensionsPlugin.cs.frame	(revision 6342)
@@ -28,4 +28,5 @@
   [Plugin("HeuristicLab.Visualization.ChartControlsExtensions", "3.3.4.$WCREV$")]
   [PluginFile("HeuristicLab.Visualization.ChartControlsExtensions-3.3.dll", PluginFileType.Assembly)]
+  [PluginDependency("HeuristicLab.Common.Resources", "3.3")]
   public class HeuristicLabVisualizationChartControlsExtensionsPlugin : PluginBase { }
 }
Index: /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HistogramControl.Designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HistogramControl.Designer.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HistogramControl.Designer.cs	(revision 6342)
@@ -0,0 +1,140 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Visualization.ChartControlsExtensions {
+  partial class HistogramControl {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.binsNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.label1 = new System.Windows.Forms.Label();
+      this.exactCheckBox = new System.Windows.Forms.CheckBox();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // chart
+      // 
+      this.chart.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                  | System.Windows.Forms.AnchorStyles.Left)
+                  | System.Windows.Forms.AnchorStyles.Right)));
+      chartArea1.Name = "ChartArea1";
+      this.chart.ChartAreas.Add(chartArea1);
+      this.chart.Location = new System.Drawing.Point(0, 27);
+      this.chart.Name = "chart";
+      series1.ChartArea = "ChartArea1";
+      series1.Name = "Series1";
+      this.chart.Series.Add(series1);
+      this.chart.Size = new System.Drawing.Size(465, 336);
+      this.chart.TabIndex = 0;
+      // 
+      // binsNumericUpDown
+      // 
+      this.binsNumericUpDown.Location = new System.Drawing.Point(91, 3);
+      this.binsNumericUpDown.Maximum = new decimal(new int[] {
+            100000,
+            0,
+            0,
+            0});
+      this.binsNumericUpDown.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+      this.binsNumericUpDown.Name = "binsNumericUpDown";
+      this.binsNumericUpDown.Size = new System.Drawing.Size(61, 20);
+      this.binsNumericUpDown.TabIndex = 1;
+      this.binsNumericUpDown.Value = new decimal(new int[] {
+            10,
+            0,
+            0,
+            0});
+      this.binsNumericUpDown.ValueChanged += new System.EventHandler(this.binsNumericUpDown_ValueChanged);
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Location = new System.Drawing.Point(3, 5);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(82, 13);
+      this.label1.TabIndex = 2;
+      this.label1.Text = "Number of Bins:";
+      // 
+      // exactCheckBox
+      // 
+      this.exactCheckBox.AutoSize = true;
+      this.exactCheckBox.CheckAlign = System.Drawing.ContentAlignment.MiddleRight;
+      this.exactCheckBox.Location = new System.Drawing.Point(158, 4);
+      this.exactCheckBox.Name = "exactCheckBox";
+      this.exactCheckBox.Size = new System.Drawing.Size(56, 17);
+      this.exactCheckBox.TabIndex = 3;
+      this.exactCheckBox.Text = "Exact:";
+      this.exactCheckBox.UseVisualStyleBackColor = true;
+      this.exactCheckBox.CheckedChanged += new System.EventHandler(this.exactCheckBox_CheckedChanged);
+      // 
+      // HistogramControl
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.exactCheckBox);
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.binsNumericUpDown);
+      this.Controls.Add(this.chart);
+      this.Name = "HistogramControl";
+      this.Size = new System.Drawing.Size(465, 363);
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.binsNumericUpDown)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private EnhancedChart chart;
+    private System.Windows.Forms.NumericUpDown binsNumericUpDown;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.CheckBox exactCheckBox;
+  }
+}
Index: /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HistogramControl.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HistogramControl.cs	(revision 6342)
+++ /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HistogramControl.cs	(revision 6342)
@@ -0,0 +1,161 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+
+namespace HeuristicLab.Visualization.ChartControlsExtensions {
+  public partial class HistogramControl : UserControl {
+    private static readonly string SeriesName = "Histogram";
+
+    private List<double> points;
+    public int NumberOfBins {
+      get { return (int)binsNumericUpDown.Value; }
+      set { binsNumericUpDown.Value = value; }
+    }
+
+    public int MinimumNumberOfBins {
+      get { return (int)binsNumericUpDown.Minimum; }
+      set { binsNumericUpDown.Minimum = value; }
+    }
+
+    public int MaximumNumberOfBins {
+      get { return (int)binsNumericUpDown.Maximum; }
+      set { binsNumericUpDown.Maximum = value; }
+    }
+
+    public int IncrementNumberOfBins {
+      get { return (int)binsNumericUpDown.Increment; }
+      set { binsNumericUpDown.Increment = value; }
+    }
+
+    public bool CalculateExactBins {
+      get { return exactCheckBox.Checked; }
+      set { exactCheckBox.Checked = value; }
+    }
+
+    public bool ShowExactCheckbox {
+      get { return exactCheckBox.Visible; }
+      set { exactCheckBox.Visible = value; }
+    }
+
+    public HistogramControl() {
+      InitializeComponent();
+      points = new List<double>();
+      InitializeChart();
+    }
+
+    public void AddPoint(double point) {
+      points.Add(point);
+      UpdateHistogram();
+    }
+
+    public void AddPoints(IEnumerable<double> points) {
+      this.points.AddRange(points);
+      UpdateHistogram();
+    }
+
+    public void ClearPoints() {
+      points.Clear();
+      UpdateHistogram();
+    }
+
+    private void InitializeChart() {
+      chart.Series.Clear();
+      Series s = chart.Series.Add(SeriesName);
+      s.ChartType = SeriesChartType.Column;
+      s.BorderColor = Color.Black;
+      s.BorderWidth = 1;
+      s.BorderDashStyle = ChartDashStyle.Solid;
+    }
+
+    private void UpdateHistogram() {
+      if (InvokeRequired) {
+        Invoke((Action)UpdateHistogram, null);
+        return;
+      }
+      Series histogramSeries = chart.Series[SeriesName];
+      histogramSeries.Points.Clear();
+
+      if (!points.Any()) return;
+      int bins = (int)binsNumericUpDown.Value;
+
+      double minValue = points.Min();
+      double maxValue = points.Max();
+      double intervalWidth = (maxValue - minValue) / bins;
+      if (intervalWidth <= 0) return;
+
+      if (!exactCheckBox.Checked) {
+        intervalWidth = HumanRoundRange(intervalWidth);
+        minValue = Math.Floor(minValue / intervalWidth) * intervalWidth;
+        maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth;
+      }
+
+      double current = minValue, intervalCenter = intervalWidth / 2.0;
+      int count = 0;
+      foreach (double v in points.OrderBy(x => x)) {
+        while (v > current + intervalWidth) {
+          histogramSeries.Points.AddXY(current + intervalCenter, count);
+          current += intervalWidth;
+          count = 0;
+        }
+        count++;
+      }
+      histogramSeries.Points.AddXY(current + intervalCenter, count);
+
+      histogramSeries["PointWidth"] = "1";
+
+      ChartArea chartArea = chart.ChartAreas[histogramSeries.ChartArea];
+      chartArea.AxisY.Title = "Frequency";
+      chartArea.AxisX.Minimum = minValue;
+      chartArea.AxisX.Maximum = maxValue;
+
+      double axisInterval = intervalWidth;
+      while ((maxValue - minValue) / axisInterval > 10.0) {
+        axisInterval *= 2.0;
+      }
+      chartArea.AxisX.Interval = axisInterval;
+    }
+
+    private double HumanRoundRange(double range) {
+      double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range)));
+      double rounding = range / base10;
+      if (rounding <= 1.5) rounding = 1;
+      else if (rounding <= 2.25) rounding = 2;
+      else if (rounding <= 3.75) rounding = 2.5;
+      else if (rounding <= 7.5) rounding = 5;
+      else rounding = 10;
+      return rounding * base10;
+    }
+
+    private void binsNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      UpdateHistogram();
+    }
+
+    private void exactCheckBox_CheckedChanged(object sender, EventArgs e) {
+      UpdateHistogram();
+    }
+  }
+}
