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 7828)
+++ trunk/sources/HeuristicLab.Analysis.Views/3.3/HeuristicLab.Analysis.Views-3.3.csproj	(revision 7829)
@@ -116,4 +116,10 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ScatterPlotView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="ScatterPlotView.Designer.cs">
+      <DependentUpon>ScatterPlotView.cs</DependentUpon>
+    </Compile>
     <None Include="Plugin.cs.frame" />
     <Compile Include="AlleleFrequencyCollectionView.cs">
Index: trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.Designer.cs	(revision 7829)
+++ trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.Designer.cs	(revision 7829)
@@ -0,0 +1,106 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 ScatterPlotView {
+    /// <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() {
+      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();
+      System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+      this.chart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
+      this.SuspendLayout();
+      // 
+      // nameTextBox
+      // 
+      this.errorProvider.SetIconAlignment(this.nameTextBox, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+      this.errorProvider.SetIconPadding(this.nameTextBox, 2);
+      this.nameTextBox.Size = new System.Drawing.Size(596, 20);
+      // 
+      // 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, 26);
+      this.chart.Name = "chart";
+      series1.ChartArea = "ChartArea1";
+      series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastPoint;
+      series1.EmptyPointStyle.BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.LeftRight;
+      series1.MarkerSize = 3;
+      series1.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
+      series1.Name = "Series1";
+      this.chart.Series.Add(series1);
+      this.chart.Size = new System.Drawing.Size(668, 378);
+      this.chart.TabIndex = 5;
+      title1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      title1.Name = "Title1";
+      title1.Text = "Scatter Plot";
+      this.chart.Titles.Add(title1);
+      // 
+      // ScatterPlotView
+      // 
+      this.AllowDrop = true;
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+      this.Controls.Add(this.chart);
+      this.Name = "ScatterPlotView";
+      this.Size = new System.Drawing.Size(668, 404);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      this.Controls.SetChildIndex(this.chart, 0);
+      this.Controls.SetChildIndex(this.nameLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
+      ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart chart;
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs	(revision 7829)
+++ trunk/sources/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs	(revision 7829)
@@ -0,0 +1,113 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Collections;
+using HeuristicLab.Core.Views;
+using HeuristicLab.MainForm;
+
+namespace HeuristicLab.Analysis.Views {
+  [View("ScatterPlot View")]
+  [Content(typeof(ScatterPlot), true)]
+  public partial class ScatterPlotView : NamedItemView {
+    public new ScatterPlot Content {
+      get { return (ScatterPlot)base.Content; }
+      set { base.Content = value; }
+    }
+
+    public ScatterPlotView() {
+      InitializeComponent();
+      chart.CustomizeAllChartAreas();
+    }
+
+    protected override void DeregisterContentEvents() {
+      Content.Points.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
+      Content.Points.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
+      Content.Points.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
+      Content.Points.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
+      Content.AxisNameChanged -= new EventHandler(Content_AxisNameChanged);
+      base.DeregisterContentEvents();
+    }
+
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.Points.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
+      Content.Points.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
+      Content.Points.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
+      Content.Points.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<PointF>>(Content_Points_Changed);
+      Content.AxisNameChanged += new EventHandler(Content_AxisNameChanged);
+    }
+
+    private void Content_Points_Changed(object sender, CollectionItemsChangedEventArgs<IndexedItem<PointF>> e) {
+      RedrawChart();
+    }
+
+    protected override void OnContentChanged() {
+      base.OnContentChanged();
+      if (Content != null) {
+        ConfigureChart();
+        RedrawChart();
+      } else {
+        ClearChart();
+      }
+    }
+
+    private void Content_AxisNameChanged(object sender, EventArgs e) {
+      ConfigureChart();
+    }
+
+    private void ConfigureChart() {
+      if (InvokeRequired) {
+        Invoke((Action)ConfigureChart);
+      } else {
+        chart.ChartAreas[0].AxisX.Title = Content.XAxisName;
+        chart.ChartAreas[0].AxisY.Title = Content.YAxisName;
+        chart.Titles[0].Text = Content.Name;
+      }
+    }
+
+    private void ClearChart() {
+      if (InvokeRequired) {
+        Invoke((Action)ClearChart);
+      } else {
+        chart.Series[0].Points.Clear();
+        chart.ChartAreas[0].AxisX.Title = String.Empty;
+        chart.ChartAreas[0].AxisY.Title = String.Empty;
+        chart.Titles[0].Text = String.Empty;
+      }
+    }
+
+    private void RedrawChart() {
+      if (InvokeRequired) {
+        Invoke((Action)RedrawChart);
+      } else {
+        chart.Series[0].Points.SuspendUpdates();
+        chart.Series[0].Points.Clear();
+        foreach (var p in Content.Points.ToArray()) {
+          chart.Series[0].Points.AddXY(p.X, p.Y);
+        }
+        chart.Series[0].Points.ResumeUpdates();
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs	(revision 7829)
+++ trunk/sources/HeuristicLab.Analysis/3.3/DataVisualization/ScatterPlot.cs	(revision 7829)
@@ -0,0 +1,203 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Analysis {
+  [Item("ScatterPlot", "A scatter plot of 2D data")]
+  [StorableClass]
+  public class ScatterPlot : NamedItem, IStringConvertibleMatrix {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Performance; }
+    }
+
+    [Storable]
+    private ObservableList<PointF> points;
+    public ObservableList<PointF> Points {
+      get { return points; }
+    }
+
+    [Storable]
+    private string xAxisName;
+    public string XAxisName {
+      get { return xAxisName; }
+      set {
+        if (value == xAxisName) return;
+        xAxisName = value;
+        OnAxesNameChanged();
+      }
+    }
+
+    [Storable]
+    private string yAxisName;
+    public string YAxisName {
+      get { return yAxisName; }
+      set {
+        if (value == yAxisName) return;
+        yAxisName = value;
+        OnAxesNameChanged();
+      }
+    }
+
+    [StorableConstructor]
+    protected ScatterPlot(bool deserializing) : base(deserializing) { }
+    protected ScatterPlot(ScatterPlot original, Cloner cloner)
+      : base(original, cloner) {
+      points = new ObservableList<PointF>(original.points);
+      xAxisName = original.xAxisName;
+      yAxisName = original.yAxisName;
+    }
+    public ScatterPlot()
+      : base() {
+      this.points = new ObservableList<PointF>();
+    }
+    public ScatterPlot(string name)
+      : base(name) {
+      this.points = new ObservableList<PointF>();
+    }
+    public ScatterPlot(string name, string description)
+      : base(name, description) {
+      this.points = new ObservableList<PointF>();
+    }
+    public ScatterPlot(string name, string description, string xAxisName, string yAxisName)
+      : base(name, description) {
+      this.points = new ObservableList<PointF>();
+      this.xAxisName = xAxisName;
+      this.yAxisName = yAxisName;
+    }
+    public ScatterPlot(IEnumerable<PointF> points)
+      : base() {
+      this.points = new ObservableList<PointF>(points);
+    }
+    public ScatterPlot(IEnumerable<PointF> points, string name)
+      : base(name) {
+      this.points = new ObservableList<PointF>(points);
+    }
+    public ScatterPlot(IEnumerable<PointF> points, string name, string description)
+      : base(name, description) {
+      this.points = new ObservableList<PointF>(points);
+    }
+    public ScatterPlot(IEnumerable<PointF> points, string name, string description, string xAxisName, string yAxisName)
+      : base(name, description) {
+      this.points = new ObservableList<PointF>(points);
+      this.xAxisName = xAxisName;
+      this.yAxisName = yAxisName;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ScatterPlot(this, cloner);
+    }
+
+    public event EventHandler AxisNameChanged;
+    protected virtual void OnAxesNameChanged() {
+      EventHandler handler = AxisNameChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+
+    #region IStringConvertibleMatrix Members
+
+    int IStringConvertibleMatrix.Rows {
+      get { return points.Count; }
+      set { throw new NotSupportedException(); }
+    }
+    int IStringConvertibleMatrix.Columns {
+      get { return 2; }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
+      get { return new string[] { xAxisName, yAxisName }; }
+      set { throw new NotSupportedException(); }
+    }
+    IEnumerable<string> IStringConvertibleMatrix.RowNames {
+      get { return Enumerable.Empty<string>(); }
+      set { throw new NotSupportedException(); }
+    }
+
+    bool IStringConvertibleMatrix.SortableView {
+      get { return false; }
+      set { throw new NotSupportedException(); }
+    }
+    bool IStringConvertibleMatrix.ReadOnly {
+      get { return true; }
+    }
+
+    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
+      if (rowIndex < points.Count && columnIndex < 2) {
+        return columnIndex == 0 ? points[rowIndex].X.ToString() : points[rowIndex].Y.ToString();
+      }
+      return string.Empty;
+    }
+
+    bool IStringConvertibleMatrix.Validate(string value, out string errorMessage) {
+      throw new NotSupportedException();
+    }
+    bool IStringConvertibleMatrix.SetValue(string value, int rowIndex, int columnIndex) {
+      throw new NotSupportedException();
+    }
+
+    public event EventHandler<EventArgs<int, int>> ItemChanged;
+    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
+      var handler = ItemChanged;
+      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
+      OnToStringChanged();
+    }
+    public event EventHandler Reset;
+    protected virtual void OnReset() {
+      var handler = Reset;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnsChanged;
+    protected virtual void OnColumnsChanged() {
+      var handler = ColumnsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowsChanged;
+    protected virtual void OnRowsChanged() {
+      var handler = RowsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ColumnNamesChanged;
+    protected virtual void OnColumnNamesChanged() {
+      var handler = ColumnNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler RowNamesChanged;
+    protected virtual void OnRowNamesChanged() {
+      var handler = RowNamesChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler SortableViewChanged;
+    protected virtual void OnSortableViewChanged() {
+      var handler = SortableViewChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+  }
+}
Index: trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 7828)
+++ trunk/sources/HeuristicLab.Analysis/3.3/HeuristicLab.Analysis-3.3.csproj	(revision 7829)
@@ -133,4 +133,5 @@
     <Compile Include="DataVisualization\HeatMap.cs" />
     <Compile Include="DataVisualization\HeatMapHistory.cs" />
+    <Compile Include="DataVisualization\ScatterPlot.cs" />
     <Compile Include="MultidimensionalScaling\MultidimensionalScaling.cs" />
     <Compile Include="MultiObjective\RankBasedParetoFrontAnalyzer.cs" />
