Index: /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.Designer.cs
===================================================================
--- /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.Designer.cs	(revision 12458)
+++ /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.Designer.cs	(revision 12459)
@@ -58,4 +58,7 @@
       this.sizeComboBox = new System.Windows.Forms.ComboBox();
       this.sizeLabel = new System.Windows.Forms.Label();
+      this.sourceLabel = new System.Windows.Forms.Label();
+      this.levelNumericUpDown = new System.Windows.Forms.NumericUpDown();
+      this.includeChildrenCheckBox = new System.Windows.Forms.CheckBox();
       ((System.ComponentModel.ISupportInitialize)(this.chart)).BeginInit();
       this.childrenGroupBox.SuspendLayout();
@@ -64,4 +67,5 @@
       this.splitContainer.Panel2.SuspendLayout();
       this.splitContainer.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.levelNumericUpDown)).BeginInit();
       this.SuspendLayout();
       // 
@@ -69,5 +73,5 @@
       // 
       this.yLabel.AutoSize = true;
-      this.yLabel.Location = new System.Drawing.Point(3, 6);
+      this.yLabel.Location = new System.Drawing.Point(305, 6);
       this.yLabel.Name = "yLabel";
       this.yLabel.Size = new System.Drawing.Size(15, 13);
@@ -79,5 +83,5 @@
       this.xLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
       this.xLabel.AutoSize = true;
-      this.xLabel.Location = new System.Drawing.Point(461, 586);
+      this.xLabel.Location = new System.Drawing.Point(725, 713);
       this.xLabel.Name = "xLabel";
       this.xLabel.Size = new System.Drawing.Size(15, 13);
@@ -101,6 +105,7 @@
       series2.YValuesPerPoint = 2;
       this.chart.Series.Add(series2);
-      this.chart.Size = new System.Drawing.Size(663, 541);
+      this.chart.Size = new System.Drawing.Size(880, 668);
       this.chart.TabIndex = 7;
+      this.chart.AxisViewChanged += new System.EventHandler<System.Windows.Forms.DataVisualization.Charting.ViewEventArgs>(this.chart_AxisViewChanged);
       // 
       // yAxisComboBox
@@ -108,5 +113,5 @@
       this.yAxisComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
       this.yAxisComboBox.FormattingEnabled = true;
-      this.yAxisComboBox.Location = new System.Drawing.Point(24, 3);
+      this.yAxisComboBox.Location = new System.Drawing.Point(326, 3);
       this.yAxisComboBox.Name = "yAxisComboBox";
       this.yAxisComboBox.Size = new System.Drawing.Size(340, 21);
@@ -119,5 +124,5 @@
       this.xAxisComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
       this.xAxisComboBox.FormattingEnabled = true;
-      this.xAxisComboBox.Location = new System.Drawing.Point(482, 583);
+      this.xAxisComboBox.Location = new System.Drawing.Point(746, 710);
       this.xAxisComboBox.Name = "xAxisComboBox";
       this.xAxisComboBox.Size = new System.Drawing.Size(340, 21);
@@ -133,7 +138,8 @@
       this.treeView.Location = new System.Drawing.Point(6, 19);
       this.treeView.Name = "treeView";
-      this.treeView.Size = new System.Drawing.Size(128, 516);
+      this.treeView.Size = new System.Drawing.Size(175, 643);
       this.treeView.TabIndex = 10;
       this.treeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterCheck);
+      this.treeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterSelect);
       // 
       // childrenGroupBox
@@ -145,5 +151,5 @@
       this.childrenGroupBox.Location = new System.Drawing.Point(3, 3);
       this.childrenGroupBox.Name = "childrenGroupBox";
-      this.childrenGroupBox.Size = new System.Drawing.Size(140, 541);
+      this.childrenGroupBox.Size = new System.Drawing.Size(187, 668);
       this.childrenGroupBox.TabIndex = 11;
       this.childrenGroupBox.TabStop = false;
@@ -165,6 +171,6 @@
       // 
       this.splitContainer.Panel2.Controls.Add(this.chart);
-      this.splitContainer.Size = new System.Drawing.Size(819, 547);
-      this.splitContainer.SplitterDistance = 146;
+      this.splitContainer.Size = new System.Drawing.Size(1083, 674);
+      this.splitContainer.SplitterDistance = 193;
       this.splitContainer.TabIndex = 12;
       // 
@@ -174,5 +180,5 @@
       this.sizeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
       this.sizeComboBox.FormattingEnabled = true;
-      this.sizeComboBox.Location = new System.Drawing.Point(542, 3);
+      this.sizeComboBox.Location = new System.Drawing.Point(806, 3);
       this.sizeComboBox.Name = "sizeComboBox";
       this.sizeComboBox.Size = new System.Drawing.Size(280, 21);
@@ -184,5 +190,5 @@
       this.sizeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
       this.sizeLabel.AutoSize = true;
-      this.sizeLabel.Location = new System.Drawing.Point(470, 6);
+      this.sizeLabel.Location = new System.Drawing.Point(734, 6);
       this.sizeLabel.Name = "sizeLabel";
       this.sizeLabel.Size = new System.Drawing.Size(66, 13);
@@ -190,4 +196,33 @@
       this.sizeLabel.Text = "Bubble Size:";
       // 
+      // sourceLabel
+      // 
+      this.sourceLabel.AutoSize = true;
+      this.sourceLabel.Location = new System.Drawing.Point(3, 6);
+      this.sourceLabel.Name = "sourceLabel";
+      this.sourceLabel.Size = new System.Drawing.Size(36, 13);
+      this.sourceLabel.TabIndex = 15;
+      this.sourceLabel.Text = "Level:";
+      // 
+      // levelNumericUpDown
+      // 
+      this.levelNumericUpDown.Location = new System.Drawing.Point(45, 4);
+      this.levelNumericUpDown.Name = "levelNumericUpDown";
+      this.levelNumericUpDown.Size = new System.Drawing.Size(43, 20);
+      this.levelNumericUpDown.TabIndex = 16;
+      this.levelNumericUpDown.ValueChanged += new System.EventHandler(this.levelNumericUpDown_ValueChanged);
+      // 
+      // includeChildrenCheckBox
+      // 
+      this.includeChildrenCheckBox.AutoSize = true;
+      this.includeChildrenCheckBox.Location = new System.Drawing.Point(94, 4);
+      this.includeChildrenCheckBox.Name = "includeChildrenCheckBox";
+      this.includeChildrenCheckBox.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
+      this.includeChildrenCheckBox.Size = new System.Drawing.Size(102, 17);
+      this.includeChildrenCheckBox.TabIndex = 17;
+      this.includeChildrenCheckBox.Text = "Include Children";
+      this.includeChildrenCheckBox.UseVisualStyleBackColor = true;
+      this.includeChildrenCheckBox.CheckedChanged += new System.EventHandler(this.includeChildrenCheckBox_CheckedChanged);
+      // 
       // BubbleChartView
       // 
@@ -196,4 +231,7 @@
       this.BackColor = System.Drawing.SystemColors.Window;
       this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+      this.Controls.Add(this.includeChildrenCheckBox);
+      this.Controls.Add(this.levelNumericUpDown);
+      this.Controls.Add(this.sourceLabel);
       this.Controls.Add(this.sizeLabel);
       this.Controls.Add(this.sizeComboBox);
@@ -204,5 +242,5 @@
       this.Controls.Add(this.yAxisComboBox);
       this.Name = "BubbleChartView";
-      this.Size = new System.Drawing.Size(825, 607);
+      this.Size = new System.Drawing.Size(1089, 734);
       ((System.ComponentModel.ISupportInitialize)(this.chart)).EndInit();
       this.childrenGroupBox.ResumeLayout(false);
@@ -211,4 +249,5 @@
       ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
       this.splitContainer.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.levelNumericUpDown)).EndInit();
       this.ResumeLayout(false);
       this.PerformLayout();
@@ -228,4 +267,7 @@
     private System.Windows.Forms.ComboBox sizeComboBox;
     private System.Windows.Forms.Label sizeLabel;
+    private System.Windows.Forms.Label sourceLabel;
+    private System.Windows.Forms.NumericUpDown levelNumericUpDown;
+    private System.Windows.Forms.CheckBox includeChildrenCheckBox;
   }
 }
Index: /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs
===================================================================
--- /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs	(revision 12458)
+++ /branches/BubbleChart/HeuristicLab.Optimization.BubbleChart/3.3/BubbleChartView.cs	(revision 12459)
@@ -22,4 +22,5 @@
 using System;
 using System.Collections.Generic;
+using System.Drawing;
 using System.Linq;
 using System.Windows.Forms;
@@ -30,4 +31,5 @@
 using HeuristicLab.Data;
 using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
 
 namespace HeuristicLab.Optimization.BubbleChart {
@@ -59,50 +61,46 @@
 
       UpdateTreeView();
+      UpdateLevelControl();
+
       UpdateComboBoxes();
       UpdateDataPoints();
       //UpdateCaption();
     }
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      levelNumericUpDown.Enabled = Content != null;
+      // ToDo
+    }
 
     #region Tree Queries
+
+    private IEnumerable<RecursiveDataItem> GetAvailableItems() {
+      return IterateCheckedNodes()
+        .Select(n => (RecursiveDataItem)n.Tag);
+    }
     private IEnumerable<string> GetAvailableKeys() {
-      var collector = new List<string>();
-      foreach (TreeNode node in treeView.Nodes)
-        GetAvailableKeys(node, collector);
-      return collector.Distinct();
-    }
-    private void GetAvailableKeys(TreeNode node, List<string> collector) {
-      var item = (RecursiveDataItem)node.Tag;
-      if (node.Checked)
-        collector.AddRange(item.Data.Keys);
-      foreach (TreeNode child in node.Nodes)
-        GetAvailableKeys(child, collector);
-    }
-
-    private IEnumerable<RecursiveDataItem> GetAvailableItems() {
-      var collector = new List<RecursiveDataItem>();
-      foreach (TreeNode child in treeView.Nodes)
-        GetAvailableItems(child, collector);
-      return collector;
-    }
-
-    private void GetAvailableItems(TreeNode node, List<RecursiveDataItem> collector) {
-      var item = (RecursiveDataItem)node.Tag;
-      if (node.Checked)
-        collector.Add(item);
-      foreach (TreeNode child in node.Nodes)
-        GetAvailableItems(child, collector);
+      return GetAvailableItems()
+        .SelectMany(n => n.Data.Keys)
+        .Distinct();
     }
     #endregion
 
     #region Update Controls
+    private void UpdateLevelControl() {
+      if (Content == null) return;
+      if (treeView.Nodes.Count > 0)
+        levelNumericUpDown.Maximum = IterateAllNodes().Max(t => t.Level);
+      else
+        levelNumericUpDown.Maximum = 0;
+    }
+
     private void UpdateTreeView() {
       treeView.Nodes.Clear();
-
-      if (Content != null) {
+      if (Content != null)
         treeView.Nodes.Add(CreateTreeNode(Content));
-      }
-
       treeView.ExpandAll();
       splitContainer.Panel1Collapsed = treeView.Nodes.Count == 0;
+      if (treeView.Nodes.Count > 0)
+        treeView.SelectedNode = treeView.Nodes[0];
     }
     private TreeNode CreateTreeNode(RecursiveDataItem item) {
@@ -114,4 +112,13 @@
         node.Nodes.Add(CreateTreeNode(child));
       return node;
+    }
+
+    private void UpdateTreeViewCheckBoxes() {
+      int level = (int)levelNumericUpDown.Value;
+      bool includeChildren = includeChildrenCheckBox.Checked;
+      //treeView.BeginUpdate();
+      foreach (var node in IterateAllNodes())
+        node.Checked = includeChildren ? node.Level >= level : node.Level == level;
+      //treeView.EndUpdate();
     }
 
@@ -240,5 +247,5 @@
       switch (sizeDimension) {
         case SizeDimension.Constant:
-          value = 2;
+          value = 5;
           break;
         default:
@@ -258,4 +265,62 @@
       }
     }
+
+    private void UpdateAxisLabels() {
+      return;
+      Axis xAxis = chart.ChartAreas[0].AxisX;
+      Axis yAxis = chart.ChartAreas[0].AxisY;
+      //mkommend: combobox.SelectedIndex could not be used as this changes during hovering over possible values
+      var xSAxisSelected = xAxisValue == null ? null : (string)xAxisComboBox.SelectedItem;
+      var ySAxisSelected = yAxisValue == null ? null : (string)yAxisComboBox.SelectedItem;
+      SetCustomAxisLabels(xAxis, xSAxisSelected);
+      SetCustomAxisLabels(yAxis, ySAxisSelected);
+      if (xAxisValue != null)
+        xAxis.Title = xAxisValue;
+      if (yAxisValue != null)
+        yAxis.Title = yAxisValue;
+    }
+    private void chart_AxisViewChanged(object sender, System.Windows.Forms.DataVisualization.Charting.ViewEventArgs e) {
+      this.UpdateAxisLabels();
+    }
+    private void SetCustomAxisLabels(Axis axis, string key) {
+      axis.CustomLabels.Clear();
+      if (categoricalMapping.ContainsKey(key)) {
+        foreach (var pair in categoricalMapping[key]) {
+          string labelText = pair.Key.ToString();
+          CustomLabel label = new CustomLabel();
+          label.ToolTip = labelText;
+          if (labelText.Length > 25)
+            labelText = labelText.Substring(0, 25) + " ... ";
+          label.Text = labelText;
+          label.GridTicks = GridTickTypes.TickMark;
+          label.FromPosition = pair.Value - 0.5;
+          label.ToPosition = pair.Value + 0.5;
+          axis.CustomLabels.Add(label);
+        }
+      } else if (key != null && Content.Data[key] is TimeSpanValue) {
+        chart.ChartAreas[0].RecalculateAxesScale();
+        for (double i = axis.Minimum; i <= axis.Maximum; i += axis.LabelStyle.Interval) {
+          TimeSpan time = TimeSpan.FromSeconds(i);
+          string x = string.Format("{0:00}:{1:00}:{2:00}", time.Hours, time.Minutes, time.Seconds);
+          axis.CustomLabels.Add(i - axis.LabelStyle.Interval / 2, i + axis.LabelStyle.Interval / 2, x);
+        }
+      }
+    }
+
+    private void UpdateNodeColors() {
+      var selectedDepth = treeView.SelectedNode != null ? treeView.SelectedNode.Level : (int?)null;
+      var selectedIndex = treeView.SelectedNode != null ? treeView.SelectedNode.Index : (int?)null;
+      foreach (TreeNode node in treeView.Nodes) {
+        UpdateNodeColor(node, selectedDepth, selectedIndex);
+      }
+    }
+    private void UpdateNodeColor(TreeNode node, int? depth, int? index) {
+      if (depth.HasValue && index.HasValue && node.Level == depth /*&& node.Index == index*/)
+        node.BackColor = Color.Yellow;
+      else
+        node.BackColor = Color.White;
+      foreach (TreeNode child in node.Nodes)
+        UpdateNodeColor(child, depth, index);
+    }
     #endregion
 
@@ -263,5 +328,10 @@
     private void treeView_AfterCheck(object sender, TreeViewEventArgs e) {
       UpdateComboBoxes();
-      UpdateDataPoints();
+      //UpdateDataPoints();
+    }
+    private void treeView_AfterSelect(object sender, TreeViewEventArgs e) {
+      //UpdateNodeColors();
+      //UpdateComboBoxes();
+      //UpdateDataPoints();
     }
 
@@ -274,5 +344,32 @@
 
       UpdateDataPoints();
-      //UpdateAxisLabels();
+      UpdateAxisLabels();
+    }
+
+    private void includeChildrenCheckBox_CheckedChanged(object sender, EventArgs e) {
+      UpdateTreeViewCheckBoxes();
+      UpdateComboBoxes();
+    }
+
+    private void levelNumericUpDown_ValueChanged(object sender, EventArgs e) {
+      UpdateTreeViewCheckBoxes();
+      UpdateComboBoxes();
+    }
+    #endregion
+
+    #region Helpers
+
+    private IEnumerable<TreeNode> IterateAllNodes() {
+      return Collect(treeView.Nodes);
+    }
+    private IEnumerable<TreeNode> IterateCheckedNodes() {
+      return IterateAllNodes().Where(t => t.Checked);
+    }
+    private IEnumerable<TreeNode> Collect(TreeNodeCollection nodes) {
+      foreach (TreeNode node in nodes) {
+        yield return node;
+        foreach (var child in Collect(node.Nodes))
+          yield return child;
+      }
     }
     #endregion
