Index: /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs
===================================================================
--- /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs	(revision 14100)
+++ /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.Designer.cs	(revision 14101)
@@ -45,4 +45,6 @@
     private void InitializeComponent() {
       this.components = new System.ComponentModel.Container();
+      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+      System.Windows.Forms.DataVisualization.Charting.Legend legend1 = new System.Windows.Forms.DataVisualization.Charting.Legend();
       this.dataTableComboBox = new System.Windows.Forms.ComboBox();
       this.dataTableLabel = new System.Windows.Forms.Label();
@@ -59,20 +61,22 @@
       this.budgetsTextBox = new System.Windows.Forms.TextBox();
       this.addBudgetsAsResultButton = new System.Windows.Forms.Button();
-      this.eachOrAllTargetCheckBox = new System.Windows.Forms.CheckBox();
+      this.aggregateTargetsCheckBox = new System.Windows.Forms.CheckBox();
       this.tabControl = new System.Windows.Forms.TabControl();
       this.byTargetTabPage = new System.Windows.Forms.TabPage();
-      this.byTargetViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
+      this.targetChart = new HeuristicLab.Visualization.ChartControlsExtensions.EnhancedChart();
+      this.boundShadingCheckBox = new System.Windows.Forms.CheckBox();
       this.byCostTabPage = new System.Windows.Forms.TabPage();
+      this.byCostViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
       this.budgetLogScalingCheckBox = new System.Windows.Forms.CheckBox();
       this.eachOrAllBudgetsCheckBox = new System.Windows.Forms.CheckBox();
       this.generateBudgetsButton = new System.Windows.Forms.Button();
-      this.byCostViewHost = new HeuristicLab.MainForm.WindowsForms.ViewHost();
       this.byTableTabPage = new System.Windows.Forms.TabPage();
+      this.ertTableView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
       this.problemComboBox = new System.Windows.Forms.ComboBox();
       this.problemLabel = new System.Windows.Forms.Label();
-      this.ertTableView = new HeuristicLab.Data.Views.StringConvertibleMatrixView();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.tabControl.SuspendLayout();
       this.byTargetTabPage.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.targetChart)).BeginInit();
       this.byCostTabPage.SuspendLayout();
       this.byTableTabPage.SuspendLayout();
@@ -139,5 +143,5 @@
       this.targetsTextBox.Location = new System.Drawing.Point(59, 8);
       this.targetsTextBox.Name = "targetsTextBox";
-      this.targetsTextBox.Size = new System.Drawing.Size(326, 20);
+      this.targetsTextBox.Size = new System.Drawing.Size(287, 20);
       this.targetsTextBox.TabIndex = 1;
       this.toolTip.SetToolTip(this.targetsTextBox, "The order of the targets is important, first to-hit targets\r\nshould be given firs" +
@@ -211,15 +215,17 @@
       this.addBudgetsAsResultButton.Click += new System.EventHandler(this.addBudgetsAsResultButton_Click);
       // 
-      // eachOrAllTargetCheckBox
-      // 
-      this.eachOrAllTargetCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
-      this.eachOrAllTargetCheckBox.AutoSize = true;
-      this.eachOrAllTargetCheckBox.Location = new System.Drawing.Point(414, 10);
-      this.eachOrAllTargetCheckBox.Name = "eachOrAllTargetCheckBox";
-      this.eachOrAllTargetCheckBox.Size = new System.Drawing.Size(36, 17);
-      this.eachOrAllTargetCheckBox.TabIndex = 2;
-      this.eachOrAllTargetCheckBox.Text = "all";
-      this.eachOrAllTargetCheckBox.UseVisualStyleBackColor = true;
-      this.eachOrAllTargetCheckBox.CheckedChanged += new System.EventHandler(this.eachOrAllTargetCheckBox_CheckedChanged);
+      // aggregateTargetsCheckBox
+      // 
+      this.aggregateTargetsCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+      this.aggregateTargetsCheckBox.AutoSize = true;
+      this.aggregateTargetsCheckBox.Checked = true;
+      this.aggregateTargetsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.aggregateTargetsCheckBox.Location = new System.Drawing.Point(352, 10);
+      this.aggregateTargetsCheckBox.Name = "aggregateTargetsCheckBox";
+      this.aggregateTargetsCheckBox.Size = new System.Drawing.Size(74, 17);
+      this.aggregateTargetsCheckBox.TabIndex = 2;
+      this.aggregateTargetsCheckBox.Text = "aggregate";
+      this.aggregateTargetsCheckBox.UseVisualStyleBackColor = true;
+      this.aggregateTargetsCheckBox.CheckedChanged += new System.EventHandler(this.aggregateTargetsCheckBox_CheckedChanged);
       // 
       // tabControl
@@ -239,8 +245,9 @@
       // byTargetTabPage
       // 
-      this.byTargetTabPage.Controls.Add(this.byTargetViewHost);
+      this.byTargetTabPage.Controls.Add(this.targetChart);
+      this.byTargetTabPage.Controls.Add(this.boundShadingCheckBox);
       this.byTargetTabPage.Controls.Add(this.targetLogScalingCheckBox);
       this.byTargetTabPage.Controls.Add(this.targetsLabel);
-      this.byTargetTabPage.Controls.Add(this.eachOrAllTargetCheckBox);
+      this.byTargetTabPage.Controls.Add(this.aggregateTargetsCheckBox);
       this.byTargetTabPage.Controls.Add(this.targetsTextBox);
       this.byTargetTabPage.Controls.Add(this.generateTargetsButton);
@@ -254,26 +261,54 @@
       this.byTargetTabPage.UseVisualStyleBackColor = true;
       // 
-      // byTargetViewHost
-      // 
-      this.byTargetViewHost.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+      // targetChart
+      // 
+      this.targetChart.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.byTargetViewHost.Caption = "View";
-      this.byTargetViewHost.Content = null;
-      this.byTargetViewHost.Enabled = false;
-      this.byTargetViewHost.Location = new System.Drawing.Point(3, 34);
-      this.byTargetViewHost.Name = "byTargetViewHost";
-      this.byTargetViewHost.ReadOnly = false;
-      this.byTargetViewHost.Size = new System.Drawing.Size(640, 324);
-      this.byTargetViewHost.TabIndex = 5;
-      this.byTargetViewHost.ViewsLabelVisible = true;
-      this.byTargetViewHost.ViewType = null;
+      chartArea1.AxisX.IsStartedFromZero = false;
+      chartArea1.AxisX.MinorGrid.Enabled = true;
+      chartArea1.AxisX.MinorGrid.LineColor = System.Drawing.Color.WhiteSmoke;
+      chartArea1.AxisX.MinorGrid.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
+      chartArea1.AxisY.Maximum = 1D;
+      chartArea1.AxisY.Minimum = 0D;
+      chartArea1.AxisY.MinorGrid.Enabled = true;
+      chartArea1.AxisY.MinorGrid.LineColor = System.Drawing.Color.WhiteSmoke;
+      chartArea1.AxisY.MinorGrid.LineDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.Dash;
+      chartArea1.Name = "ChartArea1";
+      this.targetChart.ChartAreas.Add(chartArea1);
+      legend1.Alignment = System.Drawing.StringAlignment.Center;
+      legend1.Docking = System.Windows.Forms.DataVisualization.Charting.Docking.Top;
+      legend1.Name = "Legend1";
+      this.targetChart.Legends.Add(legend1);
+      this.targetChart.Location = new System.Drawing.Point(6, 34);
+      this.targetChart.Name = "targetChart";
+      this.targetChart.Size = new System.Drawing.Size(634, 324);
+      this.targetChart.SuppressExceptions = true;
+      this.targetChart.TabIndex = 7;
+      this.targetChart.Text = "enhancedChart1";
+      this.targetChart.CustomizeLegend += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs>(this.chart_CustomizeLegend);
+      this.targetChart.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart_MouseDown);
+      this.targetChart.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart_MouseMove);
+      // 
+      // boundShadingCheckBox
+      // 
+      this.boundShadingCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+      this.boundShadingCheckBox.AutoSize = true;
+      this.boundShadingCheckBox.Checked = true;
+      this.boundShadingCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.boundShadingCheckBox.Location = new System.Drawing.Point(127, 364);
+      this.boundShadingCheckBox.Name = "boundShadingCheckBox";
+      this.boundShadingCheckBox.Size = new System.Drawing.Size(96, 17);
+      this.boundShadingCheckBox.TabIndex = 6;
+      this.boundShadingCheckBox.Text = "bound shading";
+      this.boundShadingCheckBox.UseVisualStyleBackColor = true;
+      this.boundShadingCheckBox.CheckedChanged += new System.EventHandler(this.boundShadingCheckBox_CheckedChanged);
       // 
       // byCostTabPage
       // 
+      this.byCostTabPage.Controls.Add(this.byCostViewHost);
       this.byCostTabPage.Controls.Add(this.budgetLogScalingCheckBox);
       this.byCostTabPage.Controls.Add(this.eachOrAllBudgetsCheckBox);
       this.byCostTabPage.Controls.Add(this.generateBudgetsButton);
-      this.byCostTabPage.Controls.Add(this.byCostViewHost);
       this.byCostTabPage.Controls.Add(this.budgetsLabel);
       this.byCostTabPage.Controls.Add(this.addBudgetsAsResultButton);
@@ -287,4 +322,20 @@
       this.byCostTabPage.UseVisualStyleBackColor = true;
       // 
+      // byCostViewHost
+      // 
+      this.byCostViewHost.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.byCostViewHost.Caption = "View";
+      this.byCostViewHost.Content = null;
+      this.byCostViewHost.Enabled = false;
+      this.byCostViewHost.Location = new System.Drawing.Point(6, 34);
+      this.byCostViewHost.Name = "byCostViewHost";
+      this.byCostViewHost.ReadOnly = false;
+      this.byCostViewHost.Size = new System.Drawing.Size(634, 324);
+      this.byCostViewHost.TabIndex = 12;
+      this.byCostViewHost.ViewsLabelVisible = true;
+      this.byCostViewHost.ViewType = null;
+      // 
       // budgetLogScalingCheckBox
       // 
@@ -322,20 +373,4 @@
       this.generateBudgetsButton.Click += new System.EventHandler(this.generateBudgetsButton_Click);
       // 
-      // byCostViewHost
-      // 
-      this.byCostViewHost.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.byCostViewHost.Caption = "View";
-      this.byCostViewHost.Content = null;
-      this.byCostViewHost.Enabled = false;
-      this.byCostViewHost.Location = new System.Drawing.Point(3, 34);
-      this.byCostViewHost.Name = "byCostViewHost";
-      this.byCostViewHost.ReadOnly = false;
-      this.byCostViewHost.Size = new System.Drawing.Size(640, 324);
-      this.byCostViewHost.TabIndex = 8;
-      this.byCostViewHost.ViewsLabelVisible = true;
-      this.byCostViewHost.ViewType = null;
-      // 
       // byTableTabPage
       // 
@@ -348,25 +383,4 @@
       this.byTableTabPage.Text = "Expected Runtime Tables";
       this.byTableTabPage.UseVisualStyleBackColor = true;
-      // 
-      // problemComboBox
-      // 
-      this.problemComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.problemComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-      this.problemComboBox.FormattingEnabled = true;
-      this.problemComboBox.Location = new System.Drawing.Point(69, 30);
-      this.problemComboBox.Name = "problemComboBox";
-      this.problemComboBox.Size = new System.Drawing.Size(582, 21);
-      this.problemComboBox.TabIndex = 3;
-      this.problemComboBox.SelectedIndexChanged += new System.EventHandler(this.problemComboBox_SelectedIndexChanged);
-      // 
-      // problemLabel
-      // 
-      this.problemLabel.AutoSize = true;
-      this.problemLabel.Location = new System.Drawing.Point(3, 33);
-      this.problemLabel.Name = "problemLabel";
-      this.problemLabel.Size = new System.Drawing.Size(48, 13);
-      this.problemLabel.TabIndex = 2;
-      this.problemLabel.Text = "Problem:";
       // 
       // ertTableView
@@ -382,4 +396,25 @@
       this.ertTableView.Size = new System.Drawing.Size(640, 381);
       this.ertTableView.TabIndex = 0;
+      // 
+      // problemComboBox
+      // 
+      this.problemComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.problemComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+      this.problemComboBox.FormattingEnabled = true;
+      this.problemComboBox.Location = new System.Drawing.Point(69, 30);
+      this.problemComboBox.Name = "problemComboBox";
+      this.problemComboBox.Size = new System.Drawing.Size(582, 21);
+      this.problemComboBox.TabIndex = 3;
+      this.problemComboBox.SelectedIndexChanged += new System.EventHandler(this.problemComboBox_SelectedIndexChanged);
+      // 
+      // problemLabel
+      // 
+      this.problemLabel.AutoSize = true;
+      this.problemLabel.Location = new System.Drawing.Point(3, 33);
+      this.problemLabel.Name = "problemLabel";
+      this.problemLabel.Size = new System.Drawing.Size(48, 13);
+      this.problemLabel.TabIndex = 2;
+      this.problemLabel.Text = "Problem:";
       // 
       // RunCollectionRLDView
@@ -399,4 +434,5 @@
       this.byTargetTabPage.ResumeLayout(false);
       this.byTargetTabPage.PerformLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.targetChart)).EndInit();
       this.byCostTabPage.ResumeLayout(false);
       this.byCostTabPage.PerformLayout();
@@ -423,11 +459,9 @@
     private System.Windows.Forms.TextBox budgetsTextBox;
     private System.Windows.Forms.Label budgetsLabel;
-    private System.Windows.Forms.CheckBox eachOrAllTargetCheckBox;
+    private System.Windows.Forms.CheckBox aggregateTargetsCheckBox;
     private System.Windows.Forms.TabControl tabControl;
     private System.Windows.Forms.TabPage byTargetTabPage;
-    private MainForm.WindowsForms.ViewHost byTargetViewHost;
     private System.Windows.Forms.TabPage byCostTabPage;
     private System.Windows.Forms.TabPage byTableTabPage;
-    private MainForm.WindowsForms.ViewHost byCostViewHost;
     private System.Windows.Forms.CheckBox eachOrAllBudgetsCheckBox;
     private System.Windows.Forms.Button generateBudgetsButton;
@@ -436,4 +470,7 @@
     private System.Windows.Forms.ComboBox problemComboBox;
     private Data.Views.StringConvertibleMatrixView ertTableView;
+    private Visualization.ChartControlsExtensions.EnhancedChart targetChart;
+    private MainForm.WindowsForms.ViewHost byCostViewHost;
+    private System.Windows.Forms.CheckBox boundShadingCheckBox;
   }
 }
Index: /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs
===================================================================
--- /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs	(revision 14100)
+++ /branches/PerformanceComparison/HeuristicLab.Optimization.Views/3.3/RunCollectionViews/RunCollectionRLDView.cs	(revision 14101)
@@ -20,10 +20,4 @@
 #endregion
 
-using HeuristicLab.Analysis;
-using HeuristicLab.Collections;
-using HeuristicLab.Core.Views;
-using HeuristicLab.Data;
-using HeuristicLab.MainForm;
-using HeuristicLab.MainForm.WindowsForms;
 using System;
 using System.Collections.Generic;
@@ -33,4 +27,11 @@
 using System.Linq;
 using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using HeuristicLab.Analysis;
+using HeuristicLab.Collections;
+using HeuristicLab.Core.Views;
+using HeuristicLab.Data;
+using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
 
 namespace HeuristicLab.Optimization.Views {
@@ -38,4 +39,6 @@
   [Content(typeof(RunCollection), false)]
   public partial class RunCollectionRLDView : ItemView {
+    private List<Series> invisibleTargetSeries;
+
     private const string AllRuns = "All Runs";
 
@@ -56,5 +59,11 @@
       Color.FromArgb(0x63, 0xC2, 0x16),
     };
-    private static readonly DataRowVisualProperties.DataRowLineStyle[] lineStyles = new[] {
+    private static readonly ChartDashStyle[] lineStyles = new[] {
+      ChartDashStyle.Solid,
+      ChartDashStyle.Dash,
+      ChartDashStyle.DashDot,
+      ChartDashStyle.Dot
+    };
+    private static readonly DataRowVisualProperties.DataRowLineStyle[] hlLineStyles = new[] {
       DataRowVisualProperties.DataRowLineStyle.Solid,
       DataRowVisualProperties.DataRowLineStyle.Dash,
@@ -72,8 +81,4 @@
 
     private bool suppressUpdates;
-    private readonly IndexedDataTable<double> byTargetDataTable;
-    public IndexedDataTable<double> ByTargetDataTable {
-      get { return byTargetDataTable; }
-    }
     private readonly IndexedDataTable<double> byCostDataTable;
     public IndexedDataTable<double> ByCostDataTable {
@@ -83,14 +88,9 @@
     public RunCollectionRLDView() {
       InitializeComponent();
-      byTargetDataTable = new IndexedDataTable<double>("ECDF by Target", "A data table containing the ECDF of each of a number of groups.") {
-        VisualProperties = {
-          YAxisTitle = "Proportion of reached targets",
-          YAxisMinimumFixedValue = 0,
-          YAxisMinimumAuto = false,
-          YAxisMaximumFixedValue = 1,
-          YAxisMaximumAuto = false
-        }
-      };
-      byTargetViewHost.Content = byTargetDataTable;
+      invisibleTargetSeries = new List<Series>();
+
+      targetChart.CustomizeAllChartAreas();
+      targetChart.ChartAreas[0].CursorX.Interval = 1;
+      targetChart.SuppressExceptions = true;
       byCostDataTable = new IndexedDataTable<double>("ECDF by Cost", "A data table containing the ECDF of each of a number of groups.") {
         VisualProperties = {
@@ -196,5 +196,9 @@
       dataTableComboBox.Items.Clear();
       groupComboBox.Items.Clear();
-      byTargetDataTable.Rows.Clear();
+      targetChart.ChartAreas[0].AxisX.IsLogarithmic = false;
+      targetChart.Series.Clear();
+      invisibleTargetSeries.Clear();
+      byCostDataTable.VisualProperties.XAxisLogScale = false;
+      byCostDataTable.Rows.Clear();
 
       UpdateCaption();
@@ -309,6 +313,7 @@
     private void UpdateResultsByTarget() {
       // necessary to reset log scale -> empty chart cannot use log scaling
-      byTargetDataTable.VisualProperties.XAxisLogScale = false;
-      byTargetDataTable.Rows.Clear();
+      targetChart.ChartAreas[0].AxisX.IsLogarithmic = false;
+      targetChart.Series.Clear();
+      invisibleTargetSeries.Clear();
 
       var table = (string)dataTableComboBox.SelectedItem;
@@ -324,22 +329,47 @@
       var lineStyleCount = 0;
 
+      // if the group contains multiple different problem instances we want to use the
+      // minimal maximal observed effort otherwise we run into situations where we don't
+      // have data for a certain problem instance anymore this is a special case when
+      // aggregating over multiple problem instances      
       var maxEfforts = new Dictionary<ProblemDescription, double>();
+      double minEff = double.MaxValue, maxEff = double.MinValue;
       foreach (var group in groupedRuns) {
         foreach (var problem in group.Value) {
-          double eff;
-          if (!maxEfforts.TryGetValue(problem.Key, out eff)) {
-            eff = 0.0;
-          }
+          double problemSpecificMaxEff;
+          if (!maxEfforts.TryGetValue(problem.Key, out problemSpecificMaxEff)) {
+            problemSpecificMaxEff = 0;
+          }
+          var bestKnownTarget = problem.Value.Item1;
+          var max = problem.Key.IsMaximization();
+          var worstTarget = (max ? (1 - targets.Max()) : (1 + targets.Max())) * bestKnownTarget;
+          var bestTarget = (max ? (1 - targets.Min()) : (1 + targets.Min())) * bestKnownTarget;
           foreach (var run in problem.Value.Item2) {
-            var maxEff = ((IndexedDataTable<double>)run.Results[table]).Rows.First().Values.Last().Item1;
-            if (maxEff > eff) eff = maxEff;
-          }
-          maxEfforts[problem.Key] = eff;
-        }
-      }
-      // if the group contains multiple different problems we want to use the minimal maximal observed effort
-      // otherwise we run into situations where we don't have data for a certain problem instance anymore
-      // this is a special case when aggregating over multiple problem instances
-      var maxEffort = maxEfforts.Values.Min();
+            var row = ((IndexedDataTable<double>)run.Results[table]).Rows.First().Values;
+            var a = row.FirstOrDefault(x => max ? x.Item2 >= worstTarget : x.Item2 <= worstTarget);
+            var b = row.FirstOrDefault(x => max ? x.Item2 >= bestTarget : x.Item2 <= bestTarget);
+            var firstEff = (a == default(Tuple<double, double>)) ? row.Last().Item1 : a.Item1;
+            var lastEff = (b == default(Tuple<double, double>)) ? row.Last().Item1 : b.Item1;
+            if (minEff > firstEff) minEff = firstEff;
+            if (maxEff < lastEff) maxEff = lastEff;
+            if (problemSpecificMaxEff < lastEff) problemSpecificMaxEff = lastEff;
+          }
+          maxEfforts[problem.Key] = problemSpecificMaxEff;
+        }
+      }
+      maxEff = Math.Min(maxEff, maxEfforts.Values.Min());
+
+      var minZeros = (int)Math.Floor(Math.Log10(minEff));
+      var maxZeros = (int)Math.Floor(Math.Log10(maxEff));
+      var axisMin = (decimal)Math.Pow(10, minZeros);
+      var axisMax = (decimal)Math.Pow(10, maxZeros);
+      if (!targetLogScalingCheckBox.Checked) {
+        var minAdd = (decimal)Math.Pow(10, minZeros - 1) * 2;
+        var maxAdd = (decimal)Math.Pow(10, maxZeros - 1) * 2;
+        while (axisMin + minAdd < (decimal)minEff) axisMin += minAdd;
+        while (axisMax <= (decimal)maxEff) axisMax += maxAdd;
+      } else axisMax = (decimal)Math.Pow(10, (int)Math.Ceiling(Math.Log10(maxEff)));
+      targetChart.ChartAreas[0].AxisX.Minimum = (double)axisMin;
+      targetChart.ChartAreas[0].AxisX.Maximum = (double)axisMax;
 
       foreach (var group in groupedRuns) {
@@ -358,44 +388,86 @@
             xAxisTitles.Add(resultsTable.VisualProperties.XAxisTitle);
 
-            if (eachOrAllTargetCheckBox.Checked) {
-              CalculateHitsForEachTarget(hits, misses, resultsTable.Rows.First(), problem.Key, group.Key, problem.Value.Item1, maxEffort);
-              // achiving each target can be seen as a separate run for that target only
-              noRuns += targets.Length;
+            if (aggregateTargetsCheckBox.Checked) {
+              var length = CalculateHitsForAllTargets(hits, misses, resultsTable.Rows.First(), problem.Key, group.Key, problem.Value.Item1, maxEff);
+              maxLength = Math.Max(length, maxLength);
             } else {
-              var length = CalculateHitsForAllTargets(hits, misses, resultsTable.Rows.First(), problem.Key, group.Key, problem.Value.Item1, maxEffort);
-              maxLength = Math.Max(length, maxLength);
-              noRuns++;
+              CalculateHitsForEachTarget(hits, misses, resultsTable.Rows.First(), problem.Key, group.Key, problem.Value.Item1, maxEff);
             }
-          }
-        }
-
+            noRuns++;
+          }
+        }
         foreach (var list in hits) {
-          var row = new IndexedDataRow<double>(list.Key) {
-            VisualProperties = {
-              ChartType = DataRowVisualProperties.DataRowChartType.StepLine,
-              LineWidth = 2,
-              Color = colors[colorCount],
-              LineStyle = lineStyles[lineStyleCount],
-              StartIndexZero = false
+          var row = new Series(list.Key) {
+            ChartType = SeriesChartType.StepLine,
+            BorderWidth = 2,
+            Color = colors[colorCount],
+            BorderDashStyle = lineStyles[lineStyleCount],
+          };
+          var rowShade = new Series(list.Key + "-range") {
+            IsVisibleInLegend = false,
+            ChartType = SeriesChartType.Range,
+            Color = Color.FromArgb(32, colors[colorCount])
+          };
+
+          var ecdf = 0.0;
+          var missedecdf = 0.0;
+          var iter = misses[list.Key].GetEnumerator();
+          var moreMisses = iter.MoveNext();
+          var totalTargets = noRuns;
+          if (aggregateTargetsCheckBox.Checked) totalTargets *= targets.Length;
+          var movingTargets = totalTargets;
+          foreach (var h in list.Value) {
+            while (moreMisses && iter.Current.Key <= h.Key) {
+              missedecdf += iter.Current.Value;
+              movingTargets -= iter.Current.Value;
+              if (row.Points.Count > 0 && row.Points.Last().XValue == iter.Current.Key)
+                row.Points.Last().SetValueY(ecdf / movingTargets);
+              else row.Points.AddXY(iter.Current.Key, ecdf / movingTargets);
+              if (boundShadingCheckBox.Checked) {
+                if (rowShade.Points.Count > 0 && rowShade.Points.Last().XValue == iter.Current.Key)
+                  rowShade.Points.Last().SetValueY(ecdf / totalTargets, (ecdf + missedecdf) / totalTargets);
+                else rowShade.Points.Add(new DataPoint(iter.Current.Key, new[] { ecdf / totalTargets, (ecdf + missedecdf) / totalTargets }));
+              }
+              moreMisses = iter.MoveNext();
             }
-          };
-
-          var ecdf = 0.0;
-          var iter = misses[list.Key].GetEnumerator();
-          iter.MoveNext();
-          var sumTargets = noRuns * targets.Length;
-          foreach (var h in list.Value) {
             ecdf += h.Value;
-            while (iter.Current.Key < h.Key) {
-              sumTargets -= iter.Current.Value;
-              if (!iter.MoveNext()) break;
+            if (row.Points.Count > 0 && row.Points.Last().XValue == h.Key)
+              row.Points.Last().SetValueY(ecdf / movingTargets);
+            else row.Points.AddXY(h.Key, ecdf / movingTargets);
+            if (missedecdf > 0 && boundShadingCheckBox.Checked) {
+              if (rowShade.Points.Count > 0 && rowShade.Points.Last().XValue == h.Key)
+                rowShade.Points.Last().SetValueY(ecdf / totalTargets, (ecdf + missedecdf) / totalTargets);
+              else rowShade.Points.Add(new DataPoint(h.Key, new[] { ecdf / totalTargets, (ecdf + missedecdf) / totalTargets }));
             }
-            row.Values.Add(Tuple.Create(h.Key, ecdf / sumTargets));
-          }
-
-          if (maxLength > 0 && (row.Values.Count == 0 || row.Values.Last().Item1 < maxLength))
-            row.Values.Add(Tuple.Create(maxLength, ecdf / sumTargets));
-
-          byTargetDataTable.Rows.Add(row);
+          }
+
+          while (moreMisses) {
+            // if there are misses beyond the last hit we extend the shaded area
+            missedecdf += iter.Current.Value;
+            //movingTargets -= iter.Current.Value;
+            if (row.Points.Count > 0 && row.Points.Last().XValue == iter.Current.Key)
+              row.Points.Last().SetValueY(ecdf / movingTargets);
+            else row.Points.AddXY(iter.Current.Key, ecdf / movingTargets);
+            if (boundShadingCheckBox.Checked) {
+              if (rowShade.Points.Count > 0 && rowShade.Points.Last().XValue == iter.Current.Key)
+                rowShade.Points.Last().SetValueY(ecdf / totalTargets, (ecdf + missedecdf) / totalTargets);
+              else rowShade.Points.Add(new DataPoint(iter.Current.Key, new[] { ecdf / totalTargets, (ecdf + missedecdf) / totalTargets }));
+            }
+            moreMisses = iter.MoveNext();
+          }
+
+          if (maxLength > 0 && (row.Points.Count == 0 || row.Points.Last().XValue < maxLength))
+            row.Points.AddXY(maxLength, ecdf / movingTargets);
+
+          if (row.Points.Count > 0) {
+            var point = row.Points.Last();
+            point.Label = row.Name;
+            point.MarkerStyle = MarkerStyle.Cross;
+            point.MarkerBorderWidth = 1;
+          }
+
+          ConfigureSeries(row);
+          targetChart.Series.Add(rowShade);
+          targetChart.Series.Add(row);
         }
         colorCount = (colorCount + 1) % colors.Length;
@@ -404,9 +476,9 @@
 
       if (targets.Length == 1)
-        ByTargetDataTable.VisualProperties.YAxisTitle = "Probability to be " + (targets[0] * 100) + "% worse than best";
-      else ByTargetDataTable.VisualProperties.YAxisTitle = "Proportion of reached targets";
-      byTargetDataTable.VisualProperties.XAxisTitle = string.Join(" / ", xAxisTitles);
-      byTargetDataTable.VisualProperties.XAxisLogScale = byTargetDataTable.Rows.Count > 0 && targetLogScalingCheckBox.Checked;
-
+        targetChart.ChartAreas[0].AxisY.Title = "Probability to be " + (targets[0] * 100) + "% worse than best";
+      else targetChart.ChartAreas[0].AxisY.Title = "Proportion of reached targets";
+      targetChart.ChartAreas[0].AxisX.Title = string.Join(" / ", xAxisTitles);
+      targetChart.ChartAreas[0].AxisX.IsLogarithmic = CanDisplayLogarithmic();
+      targetChart.ChartAreas[0].CursorY.Interval = 0.05;
       UpdateErtTables(groupedRuns);
     }
@@ -423,6 +495,7 @@
                                             IndexedDataRow<double> row, ProblemDescription problem,
                                             string group, double bestTarget, double maxEffort) {
-      foreach (var l in targets.Select(x => (problem.IsMaximization() ? (1 - x) : (1 + x)) * bestTarget)) {
-        var key = group + "-" + l;
+      foreach (var t in targets.Select(x => Tuple.Create((problem.IsMaximization() ? (1 - x) : (1 + x)) * bestTarget, x))) {
+        var l = t.Item1;
+        var key = group + "_" + (t.Item2 * 100) + "%_" + l;
         if (!hits.ContainsKey(key)) {
           hits.Add(key, new SortedList<double, int>());
@@ -572,5 +645,5 @@
               LineWidth = 2,
               Color = colors[colorCount],
-              LineStyle = lineStyles[lineStyleCount],
+              LineStyle = hlLineStyles[lineStyleCount],
               StartIndexZero = false
             }
@@ -688,6 +761,10 @@
 
     private void logScalingCheckBox_CheckedChanged(object sender, EventArgs e) {
-      byTargetDataTable.VisualProperties.XAxisLogScale = byTargetDataTable.Rows.Count > 0 && targetLogScalingCheckBox.Checked;
+      UpdateResultsByTarget();
       byCostDataTable.VisualProperties.XAxisLogScale = byCostDataTable.Rows.Count > 0 && budgetLogScalingCheckBox.Checked;
+    }
+
+    private void boundShadingCheckBox_CheckedChanged(object sender, EventArgs e) {
+      UpdateResultsByTarget();
     }
 
@@ -722,7 +799,5 @@
     }
 
-    private void eachOrAllTargetCheckBox_CheckedChanged(object sender, EventArgs e) {
-      var each = eachOrAllTargetCheckBox.Checked;
-      eachOrAllTargetCheckBox.Text = each ? "each" : "all";
+    private void aggregateTargetsCheckBox_CheckedChanged(object sender, EventArgs e) {
       SuspendRepaint();
       try {
@@ -918,4 +993,88 @@
     #endregion
 
+    private void ConfigureSeries(Series series) {
+      series.SmartLabelStyle.Enabled = true;
+      series.SmartLabelStyle.AllowOutsidePlotArea = LabelOutsidePlotAreaStyle.No;
+      series.SmartLabelStyle.CalloutLineAnchorCapStyle = LineAnchorCapStyle.None;
+      series.SmartLabelStyle.CalloutLineColor = series.Color;
+      series.SmartLabelStyle.CalloutLineWidth = 2;
+      series.SmartLabelStyle.CalloutStyle = LabelCalloutStyle.Underlined;
+      series.SmartLabelStyle.IsOverlappedHidden = false;
+      series.SmartLabelStyle.MaxMovingDistance = 200;
+      series.ToolTip = series.LegendText + " X = #VALX, Y = #VALY";
+    }
+
+    private void chart_MouseDown(object sender, MouseEventArgs e) {
+      HitTestResult result = targetChart.HitTest(e.X, e.Y);
+      if (result.ChartElementType == ChartElementType.LegendItem) {
+        ToggleTargetChartSeriesVisible(result.Series);
+      }
+    }
+    private void chart_MouseMove(object sender, MouseEventArgs e) {
+      HitTestResult result = targetChart.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 = targetChart.Series[legendItem.SeriesName];
+        if (series != null) {
+          bool seriesIsInvisible = invisibleTargetSeries.Any(x => x.Name == series.Name);
+          foreach (LegendCell cell in legendItem.Cells) {
+            cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
+          }
+        }
+      }
+    }
+
+    private void ToggleTargetChartSeriesVisible(Series series) {
+      var indexList = invisibleTargetSeries.FindIndex(x => x.Name == series.Name);
+      var indexChart = targetChart.Series.IndexOf(series);
+      if (targetChart.Series.Count == 1) targetChart.ChartAreas[0].AxisX.IsLogarithmic = false;
+      targetChart.Series.RemoveAt(indexChart);
+      var s = indexList >= 0 ? invisibleTargetSeries[indexList] : new Series(series.Name) {
+        Color = series.Color,
+        ChartType = series.ChartType,
+        BorderWidth = series.BorderWidth,
+        BorderDashStyle = series.BorderDashStyle
+      };
+      if (indexList < 0) {
+        // hide
+        invisibleTargetSeries.Add(series);
+        var shadeSeries = targetChart.Series.FirstOrDefault(x => x.Name == series.Name + "-range");
+        if (shadeSeries != null) {
+          if (targetChart.Series.Count == 1) targetChart.ChartAreas[0].AxisX.IsLogarithmic = false;
+          targetChart.Series.Remove(shadeSeries);
+          invisibleTargetSeries.Add(shadeSeries);
+          indexChart--;
+        }
+      } else {
+        // show
+        invisibleTargetSeries.RemoveAt(indexList);
+        var shadeSeries = invisibleTargetSeries.FirstOrDefault(x => x.Name == series.Name + "-range");
+        if (shadeSeries != null) {
+          invisibleTargetSeries.Remove(shadeSeries);
+          InsertOrAddSeries(indexChart, shadeSeries);
+          indexChart++;
+        }
+      }
+      InsertOrAddSeries(indexChart, s);
+      targetChart.ChartAreas[0].AxisX.IsLogarithmic = CanDisplayLogarithmic();
+    }
+
+    private bool CanDisplayLogarithmic() {
+      return targetLogScalingCheckBox.Checked
+        && targetChart.Series.Count > 0 // must have a series
+        && targetChart.Series.Any(x => x.Points.Count > 0) // at least one series must have points
+        && targetChart.Series.All(s => s.Points.All(p => p.XValue > 0)); // all points must be positive
+    }
+
+    private void InsertOrAddSeries(int index, Series s) {
+      if (targetChart.Series.Count <= index)
+        targetChart.Series.Add(s);
+      else targetChart.Series.Insert(index, s);
+    }
 
     private class ProblemDescription {
