Index: branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking.Views/3.4/GenealogyGraphChart.cs
===================================================================
--- branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking.Views/3.4/GenealogyGraphChart.cs	(revision 10265)
+++ branches/HeuristicLab.EvolutionTracking/HeuristicLab.EvolutionTracking.Views/3.4/GenealogyGraphChart.cs	(revision 10269)
@@ -1,24 +1,3 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2010 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;
 using System.Collections.Generic;
 using System.Drawing;
@@ -27,57 +6,63 @@
 using System.Windows.Forms;
 using HeuristicLab.Common;
-using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
 using HeuristicLab.Visualization;
 
 namespace HeuristicLab.EvolutionaryTracking.Views {
   public partial class GenealogyGraphChart : ChartControl {
-    private Dictionary<string, VisualGenealogyGraphNode> visualNodeMap; // map the uid of the genealogy graph vertex with a visual node (in this way each node is uniquely determined)
-    private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> visualArcMap;
-    private const int Diameter = 20; // node diameter
-    private int x, y; // coordinates for positioning each node
-    private const int Cx = 30, Cy = 30; // position increments
-    private VisualGenealogyGraphNode selectedGenealogyGraphNode;
-    public VisualGenealogyGraphNode SelectedGenealogyGraphNode { get { return selectedGenealogyGraphNode; } }
-    private Visualization.Rectangle targetRectangle; // provides a  rectangle mark of the currently selected genealogy graph node
+    private GenealogyGraph genealogyGraph;
+
+    private const double XIncrement = 30;
+    private const double YIncrement = 30;
+    private const double Diameter = 20;
+
+    public GenealogyGraph GenealogyGraph {
+      get { return genealogyGraph; }
+      set {
+        if (value == null) return;
+        genealogyGraph = value;
+        Clear();
+        DrawGraph(XIncrement, YIncrement, Diameter);
+      }
+    }
+
+    private void Clear() {
+      if (nodeMap == null)
+        nodeMap = new Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode>();
+      else nodeMap.Clear();
+
+      if (arcMap == null)
+        arcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>();
+      else arcMap.Clear();
+
+      Chart.Group.Clear();
+    }
+
+    private Dictionary<IGenealogyGraphNode, VisualGenealogyGraphNode> nodeMap;
+    private Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc> arcMap;
 
     public bool SimpleLineages { get; set; }
     public bool LockGenealogy { get; set; }
-
-    private bool drawing;
-
-    private SymbolicExpressionTreeGenealogyGraph graph;
-    public SymbolicExpressionTreeGenealogyGraph Graph {
-      get { return graph; }
-      internal set {
-        graph = value;
-        if (graph == null) return;
-
-        visualNodeMap = new Dictionary<string, VisualGenealogyGraphNode>();
-        visualArcMap = new Dictionary<Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>, VisualGenealogyGraphArc>();
-
-        Chart.Group.Clear();
-        DrawGraph();
-      }
-    }
-
-    private VisualGenealogyGraphNode GetVisualGenealogyGraphNode(IVertex node) {
-      VisualGenealogyGraphNode visualNode;
-      visualNodeMap.TryGetValue(node.Id, out visualNode);
-      return visualNode;
-    }
-
-    private VisualGenealogyGraphArc GetVisualGenealogyGraphArc(IVertex source, IVertex target) {
-      VisualGenealogyGraphNode visualSource;
-      VisualGenealogyGraphNode visualTarget;
-      visualNodeMap.TryGetValue(source.Id, out visualSource);
-      visualNodeMap.TryGetValue(target.Id, out visualTarget);
-      if (visualSource != null && visualTarget != null) {
-        VisualGenealogyGraphArc visualArc;
-        visualArcMap.TryGetValue(
-          new Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>(visualSource, visualTarget), out visualArc);
-        if (visualArc != null) return visualArc;
-      }
-      return null;
-    }
+    private Visualization.Rectangle TargetRectangle { get; set; }
+
+    private VisualGenealogyGraphNode GetMappedNode(IGenealogyGraphNode node) {
+      VisualGenealogyGraphNode v;
+      nodeMap.TryGetValue(node, out v);
+      return v;
+    }
+
+    private VisualGenealogyGraphArc GetMappedArc(IGenealogyGraphNode source, IGenealogyGraphNode target) {
+      VisualGenealogyGraphNode visualSource, visualTarget;
+      nodeMap.TryGetValue(source, out visualSource);
+      nodeMap.TryGetValue(target, out visualTarget);
+
+      if (visualSource == null || visualTarget == null) return null;
+
+      VisualGenealogyGraphArc arc;
+      arcMap.TryGetValue(new Tuple<VisualGenealogyGraphNode, VisualGenealogyGraphNode>(visualSource, visualTarget), out arc);
+      return arc;
+    }
+
+    private bool DrawInProgress { get; set; } // do not try to update the chart while the drawing is not finished
+    private VisualGenealogyGraphNode SelectedVisualNode { get; set; }
 
     public event MouseEventHandler GenealogyGraphNodeClicked;
@@ -88,41 +73,24 @@
 
     public GenealogyGraphChart() {
-      //      InitializeComponent();
-      Chart = new Chart(0, 0, PreferredSize.Width, PreferredSize.Height);
-      x = 0;
-      y = PreferredSize.Height + Cx + 2 * Diameter;
-      Chart.Mode = ChartMode.Select;
-    }
-
-    public void DrawGraph() {
-      if (graph == null) return;
+      InitializeComponent();
+    }
+
+    protected virtual void DrawGraph(double xIncrement, double yIncrement, double diameter) {
       Chart.UpdateEnabled = false;
-
-      drawing = true;
-
-      var layers = Graph.Nodes.GroupBy(n => n.Rank).OrderBy(g => g.Key).Select(g => new { Rank = g.Key, Nodes = g.ToList() }).ToList();
-
-      y = PreferredSize.Height + Cx + 2 * Diameter;
-
-      for (int i = 0; i != layers.Count; ++i) {
-        x = 0;
-        layers[i].Nodes.Sort((b, a) => Graph.Compare(a, b));
-        double rank = Math.Floor(layers[i].Rank);
-        if (layers[i].Rank.IsAlmost(rank)) {
-          var visualTextNode = new VisualGenealogyGraphTextLabel(Chart, x, y + 2, x + Diameter, y + Diameter) {
-            FontBrush = new SolidBrush(Color.Black),
-            Font = new Font("Arial", Diameter - 4, FontStyle.Regular, GraphicsUnit.Pixel),
-            Text = String.Format("{0:0}", rank)
-          };
-          Chart.Group.Add(visualTextNode);
-        }
-
-        // sort descending by quality (using comparison defined in GenealogyGraphNode class)
-        x += (int)Math.Floor(1.5 * Cx); // reset horizontal coordinate
-
-        foreach (var node in layers[i].Nodes) {
+      DrawInProgress = true;
+
+      var ranks = GenealogyGraph.Ranks.Select(t => new { Rank = t.Key, Nodes = t.Value }).OrderBy(p => p.Rank).ToList();
+      double x = 0;
+      double y = PreferredSize.Height + yIncrement + 2 * diameter;
+
+      foreach (var rank in ranks) {
+        var nodes = rank.Nodes.ToList();
+        nodes.Sort((a, b) => b.CompareTo(a)); // sort descending by quality
+        var nl = Environment.NewLine;
+
+        foreach (var node in nodes) {
           var pen = new Pen(Color.LightGray);
-          var nl = Environment.NewLine;
-          var visualNode = new VisualGenealogyGraphNode(Chart, x, y, x + Diameter, y + Diameter, pen, null) {
+
+          var visualNode = new VisualGenealogyGraphNode(Chart, x, y, x + diameter, y + diameter, pen, null) {
             Data = node,
             ToolTipText = "Rank: " + node.Rank + nl +
@@ -131,66 +99,34 @@
           };
           Chart.Group.Add(visualNode);
-          visualNodeMap.Add(node.Id, visualNode);
-
-          x += Cx; // increment horizontal coordinate
-        }
-
-        y -= Cy; // decrement vertical coordinate (because the origin is upside down)
-
-        // connect elites from successive layers with visual arcs
-        if (i == 0) continue;
-        var currLayer = layers[i].Nodes;
-        var prevLayer = layers[i - 1].Nodes;
-        foreach (var n in currLayer) {
-          foreach (var m in prevLayer) {
-            if (n.SymbolicExpressionTree != m.SymbolicExpressionTree) continue;
-            var v1 = GetVisualGenealogyGraphNode(n);
-            var v2 = GetVisualGenealogyGraphNode(m);
-
-            var pen = new Pen(Color.LightGray);
-            visualArcMap[Tuple.Create(v2, v1)] = AddArc(Chart, v2, v1, pen);
-          }
-        }
-      }
-      // add arcs separately (to avoid some ordering problems)
-      foreach (SymbolicExpressionTreeGenealogyGraphNode node in Graph.Nodes) {
-        VisualGenealogyGraphNode visualNode = GetVisualGenealogyGraphNode(node);
-        if (node.InEdges == null) continue;
-
-        foreach (Arc arc in node.InEdges) {
-          var visualParent = GetVisualGenealogyGraphNode(arc.Source);
+          nodeMap.Add(node, visualNode);
+
+          x += xIncrement;
+        }
+        y -= yIncrement;
+      }
+      // add arcs
+      foreach (var node in GenealogyGraph.Nodes) {
+        if (node.InArcs == null) continue;
+        var visualNode = nodeMap[node];
+        if (visualNode == null) continue;
+        foreach (var arc in node.InArcs) {
+          var parent = arc.Source;
+          var visualParent = GetMappedNode(parent);
+          if (visualParent == null) continue;
           var pen = new Pen(Color.Transparent);
-          visualArcMap[Tuple.Create(visualParent, visualNode)] = AddArc(Chart, visualParent, visualNode, pen);
-        }
-      }
-
-      // highlight the most recent common ancestor ("eve" individual)
-      //      var eve = graph.MostRecentCommonAncestor();
-      //      if (eve != null) {
-      //        var visualGraphNode = GetVisualGenealogyGraphNode(eve);
-
-      //        var brush = new SolidBrush(Color.BlueViolet);
-      //        visualGraphNode.FontBrush = brush;
-      //      }
-
-      Chart.UpdateEnabled = true;
-      Chart.EnforceUpdate();
-
-      drawing = false;
-    }
-
-    // add an arc between the source and the target nodes, using the specified pen color
-    // adds the arc to the arc lists of both nodes and to the primitive group of the chart
-    private static VisualGenealogyGraphArc AddArc(IChart chart, VisualGenealogyGraphNode source, VisualGenealogyGraphNode target, Pen pen, Brush brush = null) {
-      var arc = new VisualGenealogyGraphArc(chart, source, target, pen) { Brush = brush };
-      arc.UpdatePosition();
-      source.OutgoingArcs.Add(arc);
-      target.IncomingArcs.Add(arc);
-      chart.Group.Add(arc);
-      return arc;
-    }
-
-    protected override void pictureBox_MouseMove(object sender, MouseEventArgs e) {
-      if (!drawing) {
+          var visualArc = AddArc(Chart, visualParent, visualNode, pen);
+          arcMap.Add(Tuple.Create(visualParent, visualNode), visualArc);
+        }
+      }
+      // TODO: connect elites
+
+      Chart.UpdateEnabled = true;
+      Chart.EnforceUpdate();
+
+      DrawInProgress = false;
+    }
+
+    protected override void pictureBox_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
+      if (!DrawInProgress) {
         switch (e.Button) {
           case MouseButtons.Left:
@@ -203,6 +139,6 @@
             break;
         }
-        base.pictureBox_MouseMove(sender, e);
-      }
+      }
+      base.pictureBox_MouseMove(sender, e);
     }
 
@@ -213,18 +149,16 @@
         return;
       }
-
       if (Chart.Mode != ChartMode.Select) {
         base.pictureBox_MouseUp(sender, e);
         return;
       }
-
       var visualNodes = Chart.GetAllPrimitives(e.Location).Where(p => p is VisualGenealogyGraphNode).ToList();
       if (visualNodes.Count <= 0) {
-        selectedGenealogyGraphNode = null;
+        SelectedVisualNode = null;
         return;
       }
-      if (selectedGenealogyGraphNode == visualNodes[0]) return;
-      selectedGenealogyGraphNode = visualNodes[0] as VisualGenealogyGraphNode;
-      if (selectedGenealogyGraphNode == null) return;
+      if (SelectedVisualNode == visualNodes[0]) return;
+      SelectedVisualNode = visualNodes[0] as VisualGenealogyGraphNode;
+      if (SelectedVisualNode == null) return;
 
       if (!LockGenealogy) {
@@ -233,8 +167,8 @@
         if (ModifierKeys != Keys.Shift)
           // clear colors
-          ClearAllNodes();
+          ClearPrimitives();
         // use a rectangle to highlight the currently selected genealogy graph node
-        var gNode = selectedGenealogyGraphNode.Data;
-        var visualNode = GetVisualGenealogyGraphNode(gNode);
+        var gNode = SelectedVisualNode.Data;
+        var visualNode = GetMappedNode(gNode);
 
         DrawLineage(visualNode, n => SimpleLineages ? n.IncomingArcs.Take(1) : n.IncomingArcs, a => a.Source);
@@ -249,7 +183,9 @@
       Chart.EnforceUpdate();
 
-      if (selectedGenealogyGraphNode != null)
+      if (SelectedVisualNode != null)
         /* emit clicked event */
-        OnGenealogyGraphNodeClicked(selectedGenealogyGraphNode, e);
+        OnGenealogyGraphNodeClicked(SelectedVisualNode, e);
+
+      base.pictureBox_MouseUp(sender, e);
     }
 
@@ -273,25 +209,32 @@
 
     void MarkSelectedNode() {
-      var center = selectedGenealogyGraphNode.Center;
-      var size = selectedGenealogyGraphNode.Size;
+      var center = SelectedVisualNode.Center;
+      var size = SelectedVisualNode.Size;
       double x1 = center.X - size.Width / 2;
       double x2 = x1 + size.Width;
       double y1 = center.Y - size.Height / 2;
       double y2 = y1 + size.Height;
-      if (targetRectangle == null) {
-        targetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null);
-        Chart.Group.Add(targetRectangle);
+      if (TargetRectangle == null) {
+        TargetRectangle = new Visualization.Rectangle(Chart, x1, y1, x2, y2, new Pen(Color.Black), null);
+        Chart.Group.Add(TargetRectangle);
       } else {
-        targetRectangle.SetPosition(x1, y1, x2, y2);
-      }
-    }
-
-    public void ClearAllNodes() {
+        TargetRectangle.SetPosition(x1, y1, x2, y2);
+      }
+    }
+
+
+    private static VisualGenealogyGraphArc AddArc(IChart chart, VisualGenealogyGraphNode source, VisualGenealogyGraphNode target, Pen pen, Brush brush = null) {
+      var arc = new VisualGenealogyGraphArc(chart, source, target, pen) { Brush = brush };
+      arc.UpdatePosition();
+      source.OutgoingArcs.Add(arc);
+      target.IncomingArcs.Add(arc);
+      chart.Group.Add(arc);
+      return arc;
+    }
+
+    public virtual void ClearPrimitives() {
       foreach (var primitive in Chart.Group.Primitives) {
         if (primitive is VisualGenealogyGraphArc) {
-          var arc = primitive as VisualGenealogyGraphArc;
-          var sourceData = arc.Source.Data.SymbolicExpressionTree;
-          var targetData = arc.Target.Data.SymbolicExpressionTree;
-          primitive.Pen.Brush = sourceData != targetData ? new SolidBrush(Color.Transparent) : new SolidBrush(Color.LightGray);
+          primitive.Pen.Brush = new SolidBrush(Color.Transparent);
         } else {
           primitive.Brush = null;
@@ -299,48 +242,19 @@
       }
     }
-
-    public void HighlightNodes(IEnumerable<SymbolicExpressionTreeGenealogyGraphNode> nodes) {
+    public void HighlightNodes(IEnumerable<IGenealogyGraphNode> nodes) {
       Chart.UpdateEnabled = false;
-      ClearAllNodes();
+      ClearPrimitives();
       foreach (var node in nodes) {
-        GetVisualGenealogyGraphNode(node).Brush = new SolidBrush(node.GetColor());
-      }
-      Chart.UpdateEnabled = true;
-      Chart.EnforceUpdate();
-    }
-
-    // TODO: optimize and reduce complexity of this method
-    public void HighlightNodes(IEnumerable<ISymbolicExpressionTree> trees) {
-      foreach (var tree in trees) {
-        var graphNodes = graph.GetGraphNodes(tree);
-        foreach (var graphNode in graphNodes) {
-          GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(graphNode.GetColor());
-        }
-      }
-    }
-
-    public void HighlightArcs(IEnumerable<IEdge> arcs, Color color) {
-      foreach (var a in arcs) {
-        var arc = GetVisualGenealogyGraphArc(a.Source, a.Target);
-        if (arc != null) {
-          var source = arc.Source.Data;
-          var target = arc.Target.Data;
-          var start = new Point((int)arc.Start.X, (int)arc.Start.Y);
-          var end = new Point((int)arc.End.X, (int)arc.End.Y);
-          arc.Pen.Brush = new LinearGradientBrush(start, end, source.GetColor(), target.GetColor());
-        }
-      }
-    }
-
-    public void HighlightNode(SymbolicExpressionTreeGenealogyGraphNode graphNode, Color color) {
-      GetVisualGenealogyGraphNode(graphNode).Brush = new SolidBrush(color);
-    }
-
+        GetMappedNode(node).Brush = new SolidBrush(node.GetColor());
+      }
+      Chart.UpdateEnabled = true;
+      Chart.EnforceUpdate();
+    }
     public void HighlightAll() {
       Chart.UpdateEnabled = false;
-      foreach (var visualNode in visualNodeMap.Values) {
+      foreach (var visualNode in nodeMap.Values) {
         visualNode.Brush = new SolidBrush(visualNode.Data.GetColor());
       }
-      foreach (var arc in visualArcMap.Values) {
+      foreach (var arc in arcMap.Values) {
         var source = arc.Source.Data;
         var target = arc.Target.Data;
@@ -352,41 +266,8 @@
       Chart.EnforceUpdate();
     }
-
-    public void HighlightInDegree() {
-      Chart.UpdateEnabled = false;
-      ClearAllNodes();
-      double max = Graph.Nodes.Max(x => x.InEdges == null ? 0 : x.InEdges.Count);
-      foreach (var graphNode in Graph.Nodes) {
-        var visualNode = GetVisualGenealogyGraphNode(graphNode);
-        double deg = graphNode.InEdges == null ? 0 : graphNode.InEdges.Count;
-        int index = (int)(deg / max * ColorGradient.Colors.Count);
-        if (index == ColorGradient.Colors.Count) --index;
-        var color = ColorGradient.Colors[index];
-        visualNode.Brush = new SolidBrush(color);
-      }
-      Chart.UpdateEnabled = true;
-      Chart.EnforceUpdate();
-    }
-
-    public void HighlightOutDegree() {
-      Chart.UpdateEnabled = false;
-      ClearAllNodes();
-      var graphNodes = Graph.Nodes;
-      double max = graphNodes.Max(x => x.OutEdges == null ? 0 : x.OutEdges.Count);
-      foreach (var graphNode in graphNodes) {
-        var visualNode = GetVisualGenealogyGraphNode(graphNode);
-        double deg = graphNode.OutEdges == null ? 0 : graphNode.OutEdges.Count;
-        int index = (int)(deg / max * ColorGradient.Colors.Count);
-        if (index == ColorGradient.Colors.Count) --index;
-        var color = ColorGradient.Colors[index];
-        visualNode.Brush = new SolidBrush(color);
-      }
-      Chart.UpdateEnabled = true;
-      Chart.EnforceUpdate();
-    }
   }
 
   internal static class Util {
-    public static Color GetColor(this SymbolicExpressionTreeGenealogyGraphNode node) {
+    public static Color GetColor(this IGenealogyGraphNode node) {
       var colorIndex = (int)(node.Quality * ColorGradient.Colors.Count);
       if (colorIndex >= ColorGradient.Colors.Count) --colorIndex;
