Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs	(revision 11120)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs	(revision 11120)
@@ -0,0 +1,101 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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.Globalization;
+using System.Linq;
+using System.Text;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
+  [Item("LaTeX/PDF Formatter", "Formatter for symbolic expression trees for use with latex package tikz.")]
+  public class SymbolicExpressionTreeLatexFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
+    private readonly static Dictionary<string, string> symbolNameMap = new Dictionary<string, string>
+    {
+      {"ProgramRootSymbol", "Prog"},
+      {"StartSymbol","RPB"}
+    };
+
+    private readonly ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> layoutEngine;
+
+    public SymbolicExpressionTreeLatexFormatter()
+      : base("LaTeX/PDF Formatter", "Formatter for symbolic expression trees for use with latex package tikz.") {
+      layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) {
+        HorizontalSpacing = 2,
+        VerticalSpacing = 2,
+        NodeWidth = 8,
+        NodeHeight = 4
+      };
+    }
+
+    protected SymbolicExpressionTreeLatexFormatter(SymbolicExpressionTreeLatexFormatter original, Cloner cloner)
+      : base(original, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicExpressionTreeLatexFormatter(this, cloner);
+    }
+
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      var root = symbolicExpressionTree.Root;
+      var actualRoot = root.SubtreeCount == 0 ? root.GetSubtree(0) : root;
+      var nodeCoordinates = layoutEngine.CalculateLayout(actualRoot).ToDictionary(n => n.Content, n => new PointF(n.X, n.Y));
+      var sb = new StringBuilder();
+      var nl = Environment.NewLine;
+      double ws = 1;
+      double hs = 0.7;
+
+      sb.Append("\\documentclass[class=minimal,border=0pt]{standalone}" + nl +
+                "\\usepackage{tikz}" + nl +
+                "\\begin{document}" + nl +
+                "\\begin{tikzpicture}" + nl +
+                "\\def\\ws{1}" + nl +
+                "\\def\\hs{0.7}" + nl);
+
+      var nodeIndices = new Dictionary<ISymbolicExpressionTreeNode, int>();
+      var nodes = symbolicExpressionTree.IterateNodesBreadth().ToList();
+      for (int i = 0; i < nodes.Count; ++i) {
+        var node = nodes[i];
+        nodeIndices.Add(node, i);
+        var coord = nodeCoordinates[node];
+        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
+        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1},\\hs*{2}) {{{3}}};", i, ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
+      }
+
+      for (int i = 0; i < nodes.Count; ++i) {
+        foreach (var s in nodes[i].Subtrees) {
+          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", i, nodeIndices[s]));
+        }
+      }
+
+      sb.Append("\\end{tikzpicture}" + nl +
+                "\\end{document}" + nl);
+      return sb.ToString();
+    }
+
+    private static string EscapeLatexString(string s) {
+      return s.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}").Replace("_", "\\_");
+    }
+  }
+}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/GraphicalSymbolicExpressionTreeView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/GraphicalSymbolicExpressionTreeView.Designer.cs	(revision 11119)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/GraphicalSymbolicExpressionTreeView.Designer.cs	(revision 11120)
@@ -19,4 +19,6 @@
  */
 #endregion
+
+using System.Drawing;
 
 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
@@ -59,5 +61,5 @@
       this.symbolicExpressionTreeChart.Spacing = 5;
       this.symbolicExpressionTreeChart.TabIndex = 0;
-      this.symbolicExpressionTreeChart.TextFont = new System.Drawing.Font("Times New Roman", 6F);
+      this.symbolicExpressionTreeChart.TextFont = new System.Drawing.Font(FontFamily.GenericSerif, 8F);
       // 
       // FunctionTreeView
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views-3.4.csproj
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views-3.4.csproj	(revision 11119)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views-3.4.csproj	(revision 11120)
@@ -110,4 +110,9 @@
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Formatters\SymbolicExpressionTreeLatexFormatter.cs" />
+    <Compile Include="LayoutEngines\BoxesLayoutEngine.cs" />
+    <Compile Include="LayoutEngines\ILayoutEngine.cs" />
+    <Compile Include="LayoutEngines\LayoutNode.cs" />
+    <Compile Include="LayoutEngines\ReingoldTilfordLayoutEngine.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="SymbolicExpressionGrammarAllowedChildSymbolsControl.cs">
@@ -160,6 +165,6 @@
       <DependentUpon>SymbolicExpressionView.cs</DependentUpon>
     </Compile>
-    <Compile Include="VisualSymbolicExpressionTreeNode.cs" />
-    <Compile Include="VisualSymbolicExpressionTreeNodeConnection.cs" />
+    <Compile Include="VisualTreeNode.cs" />
+    <Compile Include="VisualTreeNodeConnection.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -276,5 +281,5 @@
   -->
   <PropertyGroup>
-   <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
 set ProjectDir=$(ProjectDir)
 set SolutionDir=$(SolutionDir)
@@ -283,5 +288,5 @@
 call PreBuildEvent.cmd
 </PreBuildEvent>
-<PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
 export ProjectDir=$(ProjectDir)
 export SolutionDir=$(SolutionDir)
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/BoxesLayoutEngine.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/BoxesLayoutEngine.cs	(revision 11120)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/BoxesLayoutEngine.cs	(revision 11120)
@@ -0,0 +1,117 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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;
+
+namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
+  public class BoxesLayoutEngine<T> : ILayoutEngine<T> where T : class {
+    public int NodeWidth { get; set; }
+    public int NodeHeight { get; set; }
+    public int HorizontalSpacing { get; set; }
+    public int VerticalSpacing { get; set; }
+
+    private readonly Func<T, IEnumerable<T>> GetChildren;
+    private readonly Func<T, int> GetLength;
+    private readonly Func<T, int> GetDepth;
+
+    public BoxesLayoutEngine(Func<T, IEnumerable<T>> GetChildren, Func<T, int> GetLength, Func<T, int> GetDepth) {
+      if (GetChildren == null) throw new ArgumentNullException("GetChildren");
+      if (GetLength == null) throw new ArgumentNullException("GetLength");
+      if (GetDepth == null) throw new ArgumentNullException("GetDepth");
+
+      this.GetChildren = GetChildren;
+      this.GetLength = GetLength;
+      this.GetDepth = GetDepth;
+    }
+
+
+    public IEnumerable<VisualTreeNode<T>> CalculateLayout(T root, float width, float height) {
+      var nodeMap = new Dictionary<T, VisualTreeNode<T>>();
+      CreateVisualNodes(root, nodeMap);
+      RecursiveLayout(nodeMap, nodeMap[root], 0, 0, (int)Math.Round(width), (int)Math.Round(height) / GetDepth(root));
+      return nodeMap.Values;
+    }
+
+    private void CreateVisualNodes(T root, Dictionary<T, VisualTreeNode<T>> map) {
+      var node = new VisualTreeNode<T>(root) {
+        PreferredWidth = NodeWidth,
+        PreferredHeight = NodeHeight
+      };
+
+      map.Add(root, node);
+      var children = GetChildren(root).ToList();
+      if (children.Any()) {
+        foreach (var child in children) {
+          CreateVisualNodes(child, map);
+        }
+      }
+    }
+
+    private void RecursiveLayout(Dictionary<T, VisualTreeNode<T>> nodeMap, VisualTreeNode<T> visualTreeNode, int x, int y, int width, int height) {
+      float center_x = x + width / 2;
+      float center_y = y + height / 2;
+      int actualWidth = width - HorizontalSpacing;
+      int actualHeight = height - VerticalSpacing;
+
+      //calculate size of node
+      if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
+        visualTreeNode.Width = visualTreeNode.PreferredWidth;
+        visualTreeNode.Height = visualTreeNode.PreferredHeight;
+        visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
+        visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
+      }
+        //width too small to draw in desired sized
+      else if (actualWidth < visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
+        visualTreeNode.Width = actualWidth;
+        visualTreeNode.Height = visualTreeNode.PreferredHeight;
+        visualTreeNode.X = x;
+        visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
+      }
+        //height too small to draw in desired sized
+      else if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight < visualTreeNode.PreferredHeight) {
+        visualTreeNode.Width = visualTreeNode.PreferredWidth;
+        visualTreeNode.Height = actualHeight;
+        visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
+        visualTreeNode.Y = y;
+      }
+        //width and height too small to draw in desired size
+      else {
+        visualTreeNode.Width = actualWidth;
+        visualTreeNode.Height = actualHeight;
+        visualTreeNode.X = x;
+        visualTreeNode.Y = y;
+      }
+      //calculate areas for the subtrees according to their tree size 
+      var node = visualTreeNode.Content;
+      var children = GetChildren(node).ToList();
+      int[] xBoundaries = new int[children.Count + 1];
+      xBoundaries[0] = x;
+      for (int i = 0; i < children.Count; i++) {
+        xBoundaries[i + 1] = (int)(xBoundaries[i] + (width * (double)GetLength(children[i])) / (GetLength(node) - 1));
+        RecursiveLayout(nodeMap, nodeMap[children[i]], xBoundaries[i], y + height, xBoundaries[i + 1] - xBoundaries[i], height);
+      }
+    }
+  }
+}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ILayoutEngine.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ILayoutEngine.cs	(revision 11120)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ILayoutEngine.cs	(revision 11120)
@@ -0,0 +1,35 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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;
+
+namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
+  interface ILayoutEngine<T> where T : class {
+    int NodeWidth { get; set; }
+    int NodeHeight { get; set; }
+    int HorizontalSpacing { get; set; }
+    int VerticalSpacing { get; set; }
+
+    IEnumerable<VisualTreeNode<T>> CalculateLayout(T root, float width, float height);
+  }
+}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/LayoutNode.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/LayoutNode.cs	(revision 11120)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/LayoutNode.cs	(revision 11120)
@@ -0,0 +1,108 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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;
+
+namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
+  internal class LayoutNode<T> : object where T : class {
+    public float Width { get; set; }
+    public float Height { get; set; }
+
+    public LayoutNode<T> NextLeft {
+      get {
+        return Children == null ? Thread : Children.First();
+      }
+    }
+    public LayoutNode<T> NextRight {
+      get {
+        return Children == null ? Thread : Children.Last();
+      }
+    }
+    public LayoutNode<T> LeftSibling {
+      get {
+        if (Parent == null) return null;
+        return Number == 0 ? null : Parent.Children[Number - 1];
+      }
+    }
+    public LayoutNode<T> LeftmostSibling {
+      get {
+        if (Parent == null) return null;
+        return Number == 0 ? null : Parent.Children[0];
+      }
+    }
+
+    public LayoutNode<T> Thread { get; set; }
+    public LayoutNode<T> Ancestor { get; set; }
+    public LayoutNode<T> Parent { get; set; }
+    public List<LayoutNode<T>> Children { get; set; }
+    public float Mod { get; set; }
+    public float Prelim { get; set; }
+    public float Change { get; set; }
+    public float Shift { get; set; }
+    public int Number { get; set; }
+    public int Level { get; set; }
+    public float X { get; set; }
+    public float Y { get; set; }
+
+    public bool IsLeaf {
+      get { return Children == null || Children.Count == 0; }
+    }
+
+    private T content;
+    public T Content {
+      get { return content; }
+      set {
+        if (value == null)
+          throw new ArgumentNullException("LayoutNode: Content cannot be null.");
+        content = value;
+      }
+    }
+    /// <summary>
+    /// Translate the position of the layout node according to the given offsets
+    /// </summary>
+    /// <param name="dx"></param>
+    /// <param name="dy"></param>
+    public void Translate(float dx, float dy) {
+      X += dx;
+      Y += dy;
+    }
+
+    public void ResetCoordinates() {
+      X = 0;
+      Y = 0;
+    }
+
+    /// <summary>
+    /// Reset layout-related parameters
+    /// </summary>
+    public void Reset() {
+      Ancestor = this;
+      Thread = null;
+      Change = 0;
+      Shift = 0;
+      Prelim = 0;
+      Mod = 0;
+      ResetCoordinates();
+    }
+  }
+}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ReingoldTilfordLayoutEngine.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ReingoldTilfordLayoutEngine.cs	(revision 11120)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ReingoldTilfordLayoutEngine.cs	(revision 11120)
@@ -0,0 +1,273 @@
+﻿
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+
+namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
+  public class ReingoldTilfordLayoutEngine<T> : ILayoutEngine<T> where T : class {
+    public int NodeWidth { get; set; }
+    public int NodeHeight { get; set; }
+    private int minHorizontalSpacing = 5;
+    public int HorizontalSpacing {
+      get { return minHorizontalSpacing; }
+      set { minHorizontalSpacing = value; }
+    }
+
+    private int minVerticalSpacing = 5;
+    public int VerticalSpacing {
+      get { return minVerticalSpacing; }
+      set { minVerticalSpacing = value; }
+    }
+
+    private readonly Func<T, IEnumerable<T>> GetChildren;
+
+    public ReingoldTilfordLayoutEngine(Func<T, IEnumerable<T>> GetChildren) {
+      this.GetChildren = GetChildren;
+    }
+
+    public IEnumerable<VisualTreeNode<T>> CalculateLayout(T root) {
+      return CalculateLayout(root, 0, 0);
+    }
+
+    public IEnumerable<VisualTreeNode<T>> CalculateLayout(T root, float width, float height) {
+      Dictionary<T, LayoutNode<T>> layoutNodeMap = new Dictionary<T, LayoutNode<T>>();
+      var layoutRoot = new LayoutNode<T> { Content = root, Width = NodeWidth, Height = NodeHeight, };
+      layoutRoot.Ancestor = layoutRoot;
+      Expand(layoutRoot, layoutNodeMap);
+
+      FirstWalk(layoutRoot);
+      SecondWalk(layoutRoot, -layoutRoot.Prelim);
+      NormalizeCoordinates(layoutNodeMap.Values);
+      if (height != 0 && width != 0) {
+        FitToBounds(width, height, layoutNodeMap.Values);
+        Center(width, height, layoutNodeMap.Values);
+      }
+
+      return layoutNodeMap.Values.Select(x => new VisualTreeNode<T>(x.Content) {
+        Width = (int)Math.Round(x.Width),
+        Height = (int)Math.Round(x.Height),
+        X = (int)Math.Round(x.X),
+        Y = (int)Math.Round(x.Y)
+      });
+    }
+
+    private void Expand(LayoutNode<T> lRoot, Dictionary<T, LayoutNode<T>> map) {
+      map.Add(lRoot.Content, lRoot);
+      var children = GetChildren(lRoot.Content).ToList();
+      if (!children.Any()) return;
+      lRoot.Children = new List<LayoutNode<T>>(children.Count);
+      for (int i = 0; i < children.Count; ++i) {
+        var node = new LayoutNode<T> {
+          Content = children[i],
+          Number = i,
+          Parent = lRoot,
+          Level = lRoot.Level + 1,
+          Width = NodeWidth,
+          Height = NodeHeight
+        };
+        node.Ancestor = node;
+        lRoot.Children.Add(node);
+        Expand(node, map);
+      }
+    }
+
+
+    /// <summary>
+    /// Transform LayoutNode coordinates so that all coordinates are positive and start from (0,0)
+    /// </summary>
+    private static void NormalizeCoordinates(IEnumerable<LayoutNode<T>> nodes) {
+      float xmin = 0, ymin = 0;
+      foreach (var node in nodes) {
+        if (xmin > node.X) xmin = node.X;
+        if (ymin > node.Y) ymin = node.Y;
+      }
+      foreach (var node in nodes) {
+        node.X -= xmin;
+        node.Y -= ymin;
+      }
+    }
+
+    private void Center(float width, float height, IEnumerable<LayoutNode<T>> nodes) {
+      // center layout on screen
+      var bounds = Bounds(nodes);
+      float dx = 0, dy = 0;
+      if (width > bounds.Width) { dx = (width - bounds.Width) / 2f; }
+      if (height > bounds.Height) { dy = (height - bounds.Height) / 2f; }
+      foreach (var node in nodes) { node.Translate(dx, dy); }
+    }
+
+    private void FitToBounds(float width, float height, IEnumerable<LayoutNode<T>> nodes) {
+      var bounds = Bounds(nodes);
+      var myWidth = bounds.Width;
+      var myHeight = bounds.Height;
+
+      if (myWidth <= width && myHeight <= height) return; // no need to fit since we are within bounds
+
+      var layers = nodes.GroupBy(node => node.Level, node => node).ToList();
+
+      if (myWidth > width) {
+        // need to scale horizontally
+        float x = width / myWidth;
+        foreach (var node in layers.SelectMany(g => g)) {
+          node.X *= x;
+          node.Width *= x;
+        }
+        float spacing = minHorizontalSpacing * x;
+        foreach (var layer in layers) {
+          var nodesLayer = layer.ToList();
+          float minWidth = float.MaxValue;
+          for (int i = 0; i < nodesLayer.Count - 1; ++i) { minWidth = Math.Min(minWidth, nodesLayer[i + 1].X - nodesLayer[i].X); }
+          float w = Math.Min(NodeWidth, minWidth - spacing);
+          foreach (var node in nodesLayer) {
+            node.X += (node.Width - w) / 2f;
+            node.Width = w;
+            //this is a simple solution to ensure that the leftmost and rightmost nodes are not drawn partially offscreen due to scaling and offset
+            //this should work well enough 99.9% of the time with no noticeable visual difference
+            if (node.X < 0) {
+              node.Width += node.X;
+              node.X = 0;
+            } else if (node.X + node.Width > width) {
+              node.Width = width - node.X;
+            }
+          }
+        }
+      }
+      if (myHeight > height) {
+        // need to scale vertically
+        float x = height / myHeight;
+        foreach (var node in layers.SelectMany(g => g)) {
+          node.Y *= x;
+          node.Height *= x;
+        }
+      }
+    }
+
+
+    /// <summary>
+    /// Returns the bounding box for this layout. When the layout is normalized, the rectangle should be [0,0,xmin,xmax].
+    /// </summary>
+    /// <returns></returns>
+    private RectangleF Bounds(IEnumerable<LayoutNode<T>> nodes) {
+      float xmin = 0, xmax = 0, ymin = 0, ymax = 0;
+      foreach (LayoutNode<T> node in nodes) {
+        float x = node.X, y = node.Y;
+        if (xmin > x) xmin = x;
+        if (xmax < x) xmax = x;
+        if (ymin > y) ymin = y;
+        if (ymax < y) ymax = y;
+      }
+      return new RectangleF(xmin, ymin, xmax + minHorizontalSpacing + NodeWidth, ymax + minVerticalSpacing + NodeHeight);
+    }
+
+    #region methods specific to the reingold-tilford layout algorithm
+    private void FirstWalk(LayoutNode<T> v) {
+      LayoutNode<T> w;
+      if (v.IsLeaf) {
+        w = v.LeftSibling;
+        if (w != null) {
+          v.Prelim = w.Prelim + minHorizontalSpacing + NodeWidth;
+        }
+      } else {
+        var defaultAncestor = v.Children[0]; // leftmost child
+
+        foreach (var child in v.Children) {
+          FirstWalk(child);
+          Apportion(child, ref defaultAncestor);
+        }
+        ExecuteShifts(v);
+        var leftmost = v.Children.First();
+        var rightmost = v.Children.Last();
+        float midPoint = (leftmost.Prelim + rightmost.Prelim) / 2;
+        w = v.LeftSibling;
+        if (w != null) {
+          v.Prelim = w.Prelim + minHorizontalSpacing + NodeWidth;
+          v.Mod = v.Prelim - midPoint;
+        } else {
+          v.Prelim = midPoint;
+        }
+      }
+    }
+
+    private void SecondWalk(LayoutNode<T> v, float m) {
+      v.X = v.Prelim + m;
+      v.Y = v.Level * (minVerticalSpacing + NodeHeight);
+      if (v.IsLeaf) return;
+      foreach (var child in v.Children) {
+        SecondWalk(child, m + v.Mod);
+      }
+    }
+
+    private void Apportion(LayoutNode<T> v, ref LayoutNode<T> defaultAncestor) {
+      var w = v.LeftSibling;
+      if (w == null) return;
+      LayoutNode<T> vip = v;
+      LayoutNode<T> vop = v;
+      LayoutNode<T> vim = w;
+      LayoutNode<T> vom = vip.LeftmostSibling;
+
+      float sip = vip.Mod;
+      float sop = vop.Mod;
+      float sim = vim.Mod;
+      float som = vom.Mod;
+
+      while (vim.NextRight != null && vip.NextLeft != null) {
+        vim = vim.NextRight;
+        vip = vip.NextLeft;
+        vom = vom.NextLeft;
+        vop = vop.NextRight;
+        vop.Ancestor = v;
+        float shift = (vim.Prelim + sim) - (vip.Prelim + sip) + minHorizontalSpacing + NodeWidth;
+        if (shift > 0) {
+          var ancestor = Ancestor(vim, v) ?? defaultAncestor;
+          MoveSubtree(ancestor, v, shift);
+          sip += shift;
+          sop += shift;
+        }
+        sim += vim.Mod;
+        sip += vip.Mod;
+        som += vom.Mod;
+        sop += vop.Mod;
+      }
+      if (vim.NextRight != null && vop.NextRight == null) {
+        vop.Thread = vim.NextRight;
+        vop.Mod += (sim - sop);
+      }
+      if (vip.NextLeft != null && vom.NextLeft == null) {
+        vom.Thread = vip.NextLeft;
+        vom.Mod += (sip - som);
+        defaultAncestor = v;
+      }
+    }
+
+    private void MoveSubtree(LayoutNode<T> wm, LayoutNode<T> wp, float shift) {
+      int subtrees = wp.Number - wm.Number; // TODO: Investigate possible bug (if the value ever happens to be zero) - happens when the tree is actually a graph (but that's outside the use case of this algorithm which only works with trees)
+      if (subtrees == 0) throw new Exception("MoveSubtree failed: check if object is really a tree (no cycles)");
+      wp.Change -= shift / subtrees;
+      wp.Shift += shift;
+      wm.Change += shift / subtrees;
+      wp.Prelim += shift;
+      wp.Mod += shift;
+    }
+
+    private void ExecuteShifts(LayoutNode<T> v) {
+      if (v.IsLeaf) return;
+      float shift = 0;
+      float change = 0;
+      for (int i = v.Children.Count - 1; i >= 0; --i) {
+        var w = v.Children[i];
+        w.Prelim += shift;
+        w.Mod += shift;
+        change += w.Change;
+        shift += (w.Shift + change);
+      }
+    }
+
+    private LayoutNode<T> Ancestor(LayoutNode<T> u, LayoutNode<T> v) {
+      var ancestor = u.Ancestor;
+      if (ancestor == null) return null;
+      return ancestor.Parent == v.Parent ? ancestor : null;
+    }
+    #endregion
+  }
+}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionGrammarAllowedChildSymbolsControl.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionGrammarAllowedChildSymbolsControl.cs	(revision 11119)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionGrammarAllowedChildSymbolsControl.cs	(revision 11120)
@@ -29,4 +29,6 @@
 using HeuristicLab.PluginInfrastructure;
 
+using VisualSymbolicExpressionTreeNode = HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.VisualTreeNode<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>;
+
 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
   public sealed partial class SymbolicExpressionGrammarAllowedChildSymbolsControl : UserControl {
@@ -103,5 +105,4 @@
 
       var tree = new SymbolicExpressionTree(new SymbolicExpressionTreeNode(Symbol));
-      symbolicExpressionTreeChart.SuspendRepaint = true;
       if (Grammar.GetMaximumSubtreeCount(Symbol) > 0) {
         for (int i = 0; i < Grammar.GetMaximumSubtreeCount(Symbol); i++) {
@@ -116,5 +117,5 @@
       }
       symbolicExpressionTreeChart.Tree = tree;
-
+      symbolicExpressionTreeChart.SuspendRepaint = true;
       foreach (var subtreeNode in tree.Root.Subtrees) {
         foreach (var allowedChildNode in subtreeNode.Subtrees) {
@@ -142,5 +143,4 @@
         }
       }
-
       symbolicExpressionTreeChart.SuspendRepaint = false;
       UpdateSelectedSymbolicExpressionTreeNodes();
@@ -153,5 +153,5 @@
         else visualNode.FillColor = Color.LightSteelBlue;
       }
-      symbolicExpressionTreeChart.Repaint();
+      symbolicExpressionTreeChart.RepaintNodes();
     }
 
@@ -162,5 +162,5 @@
 
       VisualSymbolicExpressionTreeNode clickedNode = (VisualSymbolicExpressionTreeNode)sender;
-      var selectedNode = clickedNode.SymbolicExpressionTreeNode;
+      var selectedNode = clickedNode.Content;
       if (selectedNode.SubtreeCount == 0) {
         if (!selectedSymbolicExpressionTreeNodes.Contains(selectedNode))
@@ -207,5 +207,5 @@
         var visualNode = symbolicExpressionTreeChart.FindVisualSymbolicExpressionTreeNodeAt(coordinates.X, coordinates.Y);
         if (visualNode != null) {
-          var node = visualNode.SymbolicExpressionTreeNode;
+          var node = visualNode.Content;
           var root = symbolicExpressionTreeChart.Tree.Root;
           if (node == root || node.Parent == root) e.Effect = DragDropEffects.Copy;
@@ -223,5 +223,5 @@
       var symbols = data as IEnumerable<ISymbol>;
 
-      if (node.SymbolicExpressionTreeNode == root) {
+      if (node.Content == root) {
         if (symbol != null)
           Grammar.AddAllowedChildSymbol(root.Symbol, symbol);
@@ -229,5 +229,5 @@
           foreach (var s in symbols) Grammar.AddAllowedChildSymbol(root.Symbol, s);
       } else {
-        int argumentIndex = root.IndexOfSubtree(node.SymbolicExpressionTreeNode);
+        int argumentIndex = root.IndexOfSubtree(node.Content);
         if (symbol != null)
           Grammar.AddAllowedChildSymbol(root.Symbol, symbol, argumentIndex);
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.Designer.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.Designer.cs	(revision 11119)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.Designer.cs	(revision 11120)
@@ -49,4 +49,8 @@
       this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
       this.saveImageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.exportPgfLaTeXToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.layoutEngineToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.reingoldTilfordToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.boxesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
       this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
       this.contextMenuStrip.SuspendLayout();
@@ -56,24 +60,56 @@
       // 
       this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.saveImageToolStripMenuItem});
+            this.saveImageToolStripMenuItem,
+            this.exportPgfLaTeXToolStripMenuItem,
+            this.layoutEngineToolStripMenuItem});
       this.contextMenuStrip.Name = "contextMenuStrip";
-      this.contextMenuStrip.Size = new System.Drawing.Size(135, 26);
+      this.contextMenuStrip.Size = new System.Drawing.Size(166, 70);
       // 
       // saveImageToolStripMenuItem
       // 
       this.saveImageToolStripMenuItem.Name = "saveImageToolStripMenuItem";
-      this.saveImageToolStripMenuItem.Size = new System.Drawing.Size(134, 22);
+      this.saveImageToolStripMenuItem.Size = new System.Drawing.Size(165, 22);
       this.saveImageToolStripMenuItem.Text = "Save Image";
       this.saveImageToolStripMenuItem.Click += new System.EventHandler(this.saveImageToolStripMenuItem_Click);
+      // 
+      // exportPgfLaTeXToolStripMenuItem
+      // 
+      this.exportPgfLaTeXToolStripMenuItem.Name = "exportPgfLaTeXToolStripMenuItem";
+      this.exportPgfLaTeXToolStripMenuItem.Size = new System.Drawing.Size(165, 22);
+      this.exportPgfLaTeXToolStripMenuItem.Text = "Export Pgf/LaTeX";
+      this.exportPgfLaTeXToolStripMenuItem.Click += new System.EventHandler(this.exportLatexToolStripMenuItem_Click);
+      // 
+      // layoutEngineToolStripMenuItem
+      // 
+      this.layoutEngineToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.reingoldTilfordToolStripMenuItem,
+            this.boxesToolStripMenuItem});
+      this.layoutEngineToolStripMenuItem.Name = "layoutEngineToolStripMenuItem";
+      this.layoutEngineToolStripMenuItem.Size = new System.Drawing.Size(165, 22);
+      this.layoutEngineToolStripMenuItem.Text = "Layout Engine:";
+      // 
+      // reingoldTilfordToolStripMenuItem
+      // 
+      this.reingoldTilfordToolStripMenuItem.Name = "reingoldTilfordToolStripMenuItem";
+      this.reingoldTilfordToolStripMenuItem.Size = new System.Drawing.Size(161, 22);
+      this.reingoldTilfordToolStripMenuItem.Text = "Reingold-Tilford";
+      this.reingoldTilfordToolStripMenuItem.Click += new System.EventHandler(this.reingoldTilfordToolStripMenuItem_Click);
+      // 
+      // boxesToolStripMenuItem
+      // 
+      this.boxesToolStripMenuItem.Name = "boxesToolStripMenuItem";
+      this.boxesToolStripMenuItem.Size = new System.Drawing.Size(161, 22);
+      this.boxesToolStripMenuItem.Text = "Boxes";
+      this.boxesToolStripMenuItem.Click += new System.EventHandler(this.boxesToolStripMenuItem_Click);
       // 
       // saveFileDialog
       // 
       this.saveFileDialog.Filter = "Bitmap (*.bmp)|*.bmp|EMF (*.emf)|*.emf";
-      this.saveFileDialog.FilterIndex = 1;
+      // 
       // SymbolicExpressionTreeChart
       // 
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
       this.ContextMenuStrip = this.contextMenuStrip;
+      this.DoubleBuffered = true;
       this.Name = "SymbolicExpressionTreeChart";
       this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.SymbolicExpressionTreeChart_MouseClick);
@@ -93,4 +129,8 @@
     protected System.Windows.Forms.ToolStripMenuItem saveImageToolStripMenuItem;
     protected System.Windows.Forms.SaveFileDialog saveFileDialog;
+    private System.Windows.Forms.ToolStripMenuItem exportPgfLaTeXToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem layoutEngineToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem reingoldTilfordToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem boxesToolStripMenuItem;
   }
 }
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs	(revision 11119)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs	(revision 11120)
@@ -24,12 +24,21 @@
 using System.Drawing;
 using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
 using System.Windows.Forms;
+
 
 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
   public partial class SymbolicExpressionTreeChart : UserControl {
     private Image image;
-    private StringFormat stringFormat;
-    private Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode> visualTreeNodes;
-    private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection> visualLines;
+    private readonly StringFormat stringFormat;
+    private Dictionary<ISymbolicExpressionTreeNode, VisualTreeNode<ISymbolicExpressionTreeNode>> visualTreeNodes;
+    private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection> visualLines;
+    private ILayoutEngine<ISymbolicExpressionTreeNode> layoutEngine;
+
+    private const int preferredNodeWidth = 70;
+    private const int preferredNodeHeight = 46;
+    private int minHorizontalDistance = 30;
+    private int minVerticalDistance = 30;
 
     public SymbolicExpressionTreeChart() {
@@ -40,5 +49,16 @@
       this.lineColor = Color.Black;
       this.backgroundColor = Color.White;
-      this.textFont = new Font("Times New Roman", 8);
+      this.textFont = new Font(FontFamily.GenericSansSerif, 12);
+
+      visualTreeNodes = new Dictionary<ISymbolicExpressionTreeNode, VisualTreeNode<ISymbolicExpressionTreeNode>>();
+      visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection>();
+
+      layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) {
+        NodeWidth = preferredNodeWidth,
+        NodeHeight = preferredNodeHeight,
+        HorizontalSpacing = minHorizontalDistance,
+        VerticalSpacing = minVerticalDistance
+      };
+      reingoldTilfordToolStripMenuItem.Checked = true;
     }
 
@@ -48,4 +68,5 @@
     }
 
+    #region Public properties
     private int spacing;
     public int Spacing {
@@ -89,12 +110,4 @@
       set {
         tree = value;
-        visualTreeNodes = new Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode>();
-        visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection>();
-        if (tree != null) {
-          foreach (ISymbolicExpressionTreeNode node in tree.IterateNodesPrefix()) {
-            visualTreeNodes[node] = new VisualSymbolicExpressionTreeNode(node);
-            if (node.Parent != null) visualLines[Tuple.Create(node.Parent, node)] = new VisualSymbolicExpressionTreeNodeConnection();
-          }
-        }
         Repaint();
       }
@@ -106,4 +119,5 @@
       set { suspendRepaint = value; }
     }
+    #endregion
 
     protected override void OnPaint(PaintEventArgs e) {
@@ -115,7 +129,16 @@
       if (this.Width <= 1 || this.Height <= 1)
         this.image = new Bitmap(1, 1);
-      else
+      else {
         this.image = new Bitmap(Width, Height);
+      }
       this.Repaint();
+    }
+
+    public event EventHandler Repainted;//expose this event to notify the parent control that the tree was repainted
+    protected virtual void OnRepaint(object sender, EventArgs e) {
+      var repainted = Repainted;
+      if (repainted != null) {
+        repainted(sender, e);
+      }
     }
 
@@ -124,4 +147,5 @@
         this.GenerateImage();
         this.Refresh();
+        OnRepaint(this, EventArgs.Empty);
       }
     }
@@ -134,4 +158,9 @@
           foreach (var visualNode in visualTreeNodes.Values) {
             DrawTreeNode(graphics, visualNode);
+            if (visualNode.Content.SubtreeCount > 0) {
+              foreach (var visualSubtree in visualNode.Content.Subtrees.Select(s => visualTreeNodes[s])) {
+                DrawLine(graphics, visualNode, visualSubtree);
+              }
+            }
           }
         }
@@ -140,5 +169,5 @@
     }
 
-    public void RepaintNode(VisualSymbolicExpressionTreeNode visualNode) {
+    public void RepaintNode(VisualTreeNode<ISymbolicExpressionTreeNode> visualNode) {
       if (!suspendRepaint) {
         using (var graphics = Graphics.FromImage(image)) {
@@ -157,11 +186,10 @@
         graphics.Clear(backgroundColor);
         if (tree != null) {
-          int height = this.Height / tree.Depth;
-          DrawFunctionTree(tree, graphics, 0, 0, this.Width, height);
-        }
-      }
-    }
-
-    public VisualSymbolicExpressionTreeNode GetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) {
+          DrawFunctionTree(graphics, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance);
+        }
+      }
+    }
+
+    public VisualTreeNode<ISymbolicExpressionTreeNode> GetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) {
       if (visualTreeNodes.ContainsKey(symbolicExpressionTreeNode))
         return visualTreeNodes[symbolicExpressionTreeNode];
@@ -169,8 +197,8 @@
     }
 
-    public VisualSymbolicExpressionTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) {
+    public VisualTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) {
       if (child.Parent != parent) throw new ArgumentException();
       var key = Tuple.Create(parent, child);
-      VisualSymbolicExpressionTreeNodeConnection connection = null;
+      VisualTreeNodeConnection connection = null;
       visualLines.TryGetValue(key, out connection);
       return connection;
@@ -186,5 +214,5 @@
 
     protected virtual void SymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) {
-      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
+      var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
       if (visualTreeNode != null) {
         OnSymbolicExpressionTreeNodeClicked(visualTreeNode, e);
@@ -200,5 +228,5 @@
 
     protected virtual void SymbolicExpressionTreeChart_MouseDoubleClick(object sender, MouseEventArgs e) {
-      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
+      VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
       if (visualTreeNode != null)
         OnSymbolicExpressionTreeNodeDoubleClicked(visualTreeNode, e);
@@ -212,5 +240,5 @@
     }
 
-    private VisualSymbolicExpressionTreeNode draggedSymbolicExpressionTree;
+    private VisualTreeNode<ISymbolicExpressionTreeNode> draggedSymbolicExpressionTree;
     private MouseButtons dragButtons;
     private void SymbolicExpressionTreeChart_MouseDown(object sender, MouseEventArgs e) {
@@ -224,5 +252,5 @@
 
     private void SymbolicExpressionTreeChart_MouseMove(object sender, MouseEventArgs e) {
-      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
+      VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
       if (draggedSymbolicExpressionTree != null &&
         draggedSymbolicExpressionTree != visualTreeNode) {
@@ -239,5 +267,5 @@
     }
 
-    public VisualSymbolicExpressionTreeNode FindVisualSymbolicExpressionTreeNodeAt(int x, int y) {
+    public VisualTreeNode<ISymbolicExpressionTreeNode> FindVisualSymbolicExpressionTreeNodeAt(int x, int y) {
       foreach (var visualTreeNode in visualTreeNodes.Values) {
         if (x >= visualTreeNode.X && x <= visualTreeNode.X + visualTreeNode.Width &&
@@ -249,103 +277,51 @@
     #endregion
 
+    private void CalculateLayout(int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) {
+      layoutEngine.NodeWidth = preferredWidth;
+      layoutEngine.NodeHeight = preferredHeight;
+      layoutEngine.HorizontalSpacing = minHDistance;
+      layoutEngine.VerticalSpacing = minVDistance;
+
+      var actualRoot = tree.Root;
+      if (actualRoot.Symbol is ProgramRootSymbol && actualRoot.SubtreeCount == 1) {
+        actualRoot = tree.Root.GetSubtree(0);
+      }
+
+      var visualNodes = layoutEngine.CalculateLayout(actualRoot, Width, Height).ToList();
+      visualTreeNodes = visualNodes.ToDictionary(x => x.Content, x => x);
+      visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection>();
+      foreach (var node in visualNodes.Select(n => n.Content)) {
+        foreach (var subtree in node.Subtrees) {
+          visualLines.Add(new Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(node, subtree), new VisualTreeNodeConnection());
+        }
+      }
+    }
+
     #region methods for painting the symbolic expression tree
-    private void DrawFunctionTree(ISymbolicExpressionTree tree, Graphics graphics, int x, int y, int width, int height) {
-      DrawFunctionTree(tree.Root, graphics, x, y, width, height, Point.Empty);
-    }
-
-    /// <summary>
-    /// 
-    /// </summary>
-    /// <param name="functionTree"> function tree to draw</param>
-    /// <param name="graphics">graphics object to draw on</param>
-    /// <param name="x">x coordinate of drawing area</param>
-    /// <param name="y">y coordinate of drawing area</param>
-    /// <param name="width">width of drawing area</param>
-    /// <param name="height">height of drawing area</param>
-    private void DrawFunctionTree(ISymbolicExpressionTreeNode node, Graphics graphics, int x, int y, int width, int height, Point connectionPoint) {
-      VisualSymbolicExpressionTreeNode visualTreeNode = visualTreeNodes[node];
-      float center_x = x + width / 2;
-      float center_y = y + height / 2;
-      int actualWidth = width - spacing;
-      int actualHeight = height - spacing;
-
-      using (var textBrush = new SolidBrush(visualTreeNode.TextColor))
-      using (var nodeLinePen = new Pen(visualTreeNode.LineColor))
-      using (var nodeFillBrush = new SolidBrush(visualTreeNode.FillColor)) {
-
-        //calculate size of node
-        if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
-          visualTreeNode.Width = visualTreeNode.PreferredWidth;
-          visualTreeNode.Height = visualTreeNode.PreferredHeight;
-          visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
-          visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
-        }
-          //width too small to draw in desired sized
-        else if (actualWidth < visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
-          visualTreeNode.Width = actualWidth;
-          visualTreeNode.Height = visualTreeNode.PreferredHeight;
-          visualTreeNode.X = x;
-          visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
-        }
-          //height too small to draw in desired sized
-        else if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight < visualTreeNode.PreferredHeight) {
-          visualTreeNode.Width = visualTreeNode.PreferredWidth;
-          visualTreeNode.Height = actualHeight;
-          visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
-          visualTreeNode.Y = y;
-        }
-          //width and height too small to draw in desired size
-        else {
-          visualTreeNode.Width = actualWidth;
-          visualTreeNode.Height = actualHeight;
-          visualTreeNode.X = x;
-          visualTreeNode.Y = y;
-        }
-
-        //draw terminal node
-        if (node.SubtreeCount == 0) {
-          graphics.FillRectangle(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
-          graphics.DrawRectangle(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
-        } else {
-          graphics.FillEllipse(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
-          graphics.DrawEllipse(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
-        }
-
-        //draw name of symbol
-        var text = node.ToString();
-        graphics.DrawString(text, textFont, textBrush, new RectangleF(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height), stringFormat);
-
-        //draw connection line to parent node
-        if (!connectionPoint.IsEmpty && node.Parent != null) {
-          var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(node.Parent, node);
-          using (Pen linePen = new Pen(visualLine.LineColor)) {
+    private void DrawFunctionTree(Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) {
+      CalculateLayout(preferredWidth, preferredHeight, minHDistance, minVDistance);
+      var visualNodes = visualTreeNodes.Values;
+      //draw nodes and connections
+      foreach (var visualNode in visualNodes) {
+        DrawTreeNode(graphics, visualNode);
+        var node = visualNode.Content;
+        foreach (var subtree in node.Subtrees) {
+          var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(node, subtree);
+          var visualSubtree = visualTreeNodes[subtree];
+          var origin = new Point(visualNode.X + visualNode.Width / 2, visualNode.Y + visualNode.Height);
+          var target = new Point(visualSubtree.X + visualSubtree.Width / 2, visualSubtree.Y);
+          graphics.Clip = new Region(new Rectangle(Math.Min(origin.X, target.X), origin.Y, Math.Max(origin.X, target.X), target.Y));
+          using (var linePen = new Pen(visualLine.LineColor)) {
             linePen.DashStyle = visualLine.DashStyle;
-            graphics.DrawLine(linePen, connectionPoint, new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y));
+            graphics.DrawLine(linePen, origin, target);
           }
         }
-
-        //calculate areas for the subtrees according to their tree size and call drawFunctionTree
-        Point connectFrom = new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y + visualTreeNode.Height);
-        int[] xBoundaries = new int[node.SubtreeCount + 1];
-        xBoundaries[0] = x;
-        for (int i = 0; i < node.SubtreeCount; i++) {
-          xBoundaries[i + 1] = (int)(xBoundaries[i] + (width * (double)node.GetSubtree(i).GetLength()) / (node.GetLength() - 1));
-          DrawFunctionTree(node.GetSubtree(i), graphics, xBoundaries[i], y + height, xBoundaries[i + 1] - xBoundaries[i], height, connectFrom);
-        }
-      }
-    }
-
-    protected void DrawTreeNode(VisualSymbolicExpressionTreeNode visualTreeNode) {
-      using (var graphics = Graphics.FromImage(image)) {
-        graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
-        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
-        DrawTreeNode(graphics, visualTreeNode);
-      }
-    }
-
-    protected void DrawTreeNode(Graphics graphics, VisualSymbolicExpressionTreeNode visualTreeNode) {
+      }
+    }
+
+    protected void DrawTreeNode(Graphics graphics, VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode) {
       graphics.Clip = new Region(new Rectangle(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width + 1, visualTreeNode.Height + 1));
       graphics.Clear(backgroundColor);
-      var node = visualTreeNode.SymbolicExpressionTreeNode;
+      var node = visualTreeNode.Content;
       using (var textBrush = new SolidBrush(visualTreeNode.TextColor))
       using (var nodeLinePen = new Pen(visualTreeNode.LineColor))
@@ -364,6 +340,16 @@
       }
     }
+
+    protected void DrawLine(Graphics graphics, VisualTreeNode<ISymbolicExpressionTreeNode> startNode, VisualTreeNode<ISymbolicExpressionTreeNode> endNode) {
+      var origin = new Point(startNode.X + startNode.Width / 2, startNode.Y + startNode.Height);
+      var target = new Point(endNode.X + endNode.Width / 2, endNode.Y);
+      graphics.Clip = new Region(new Rectangle(Math.Min(origin.X, target.X), origin.Y, Math.Max(origin.X, target.X), target.Y));
+      var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(startNode.Content, endNode.Content);
+      using (var linePen = new Pen(visualLine.LineColor)) {
+        linePen.DashStyle = visualLine.DashStyle;
+        graphics.DrawLine(linePen, origin, target);
+      }
+    }
     #endregion
-
     #region save image
     private void saveImageToolStripMenuItem_Click(object sender, EventArgs e) {
@@ -380,6 +366,5 @@
       Image image = new Bitmap(Width, Height);
       using (Graphics g = Graphics.FromImage(image)) {
-        int height = this.Height / tree.Depth;
-        DrawFunctionTree(tree, g, 0, 0, Width, height);
+        DrawFunctionTree(g, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance);
       }
       image.Save(filename);
@@ -391,6 +376,5 @@
         using (Metafile file = new Metafile(filename, g.GetHdc())) {
           using (Graphics emfFile = Graphics.FromImage(file)) {
-            int height = this.Height / tree.Depth;
-            DrawFunctionTree(tree, emfFile, 0, 0, Width, height);
+            DrawFunctionTree(emfFile, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance);
           }
         }
@@ -399,4 +383,44 @@
     }
     #endregion
+    #region export pgf/tikz
+    private void exportLatexToolStripMenuItem_Click(object sender, EventArgs e) {
+      var t = Tree;
+      if (t == null) return;
+      using (var dialog = new SaveFileDialog { Filter = "Tex (*.tex)|*.tex" }) {
+        if (dialog.ShowDialog() != DialogResult.OK) return;
+        string filename = dialog.FileName.ToLower();
+        var formatter = new SymbolicExpressionTreeLatexFormatter();
+        File.WriteAllText(filename, formatter.Format(t));
+      }
+    }
+    #endregion
+
+    private void reingoldTilfordToolStripMenuItem_Click(object sender, EventArgs e) {
+      minHorizontalDistance = 30;
+      minVerticalDistance = 30;
+      layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) {
+        NodeWidth = preferredNodeWidth,
+        NodeHeight = preferredNodeHeight,
+        HorizontalSpacing = minHorizontalDistance,
+        VerticalSpacing = minVerticalDistance
+      };
+      reingoldTilfordToolStripMenuItem.Checked = true;
+      boxesToolStripMenuItem.Checked = false;
+      Repaint();
+    }
+
+    private void boxesToolStripMenuItem_Click(object sender, EventArgs e) {
+      minHorizontalDistance = 5;
+      minVerticalDistance = 5;
+      layoutEngine = new BoxesLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees, n => n.GetLength(), n => n.GetDepth()) {
+        NodeWidth = preferredNodeWidth,
+        NodeHeight = preferredNodeHeight,
+        HorizontalSpacing = minHorizontalDistance,
+        VerticalSpacing = minVerticalDistance
+      };
+      reingoldTilfordToolStripMenuItem.Checked = false;
+      boxesToolStripMenuItem.Checked = true;
+      Repaint();
+    }
   }
 }
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionView.Designer.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionView.Designer.cs	(revision 11119)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionView.Designer.cs	(revision 11120)
@@ -52,8 +52,9 @@
       // textBox
       // 
-      this.textBox.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.textBox.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.textBox.BackColor = System.Drawing.Color.White;
+      this.textBox.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
       this.textBox.Location = new System.Drawing.Point(3, 30);
       this.textBox.Multiline = true;
@@ -66,6 +67,6 @@
       // formattersComboBox
       // 
-      this.formattersComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.formattersComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.formattersComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
       this.formattersComboBox.FormattingEnabled = true;
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionView.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionView.cs	(revision 11119)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionView.cs	(revision 11120)
@@ -78,4 +78,5 @@
       UpdateTextbox();
     }
+
   }
 }
Index: able/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualSymbolicExpressionTreeNode.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualSymbolicExpressionTreeNode.cs	(revision 11119)
+++ 	(revision )
@@ -1,129 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2013 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;
-
-namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
-  public class VisualSymbolicExpressionTreeNode : object {
-    private static readonly Color defaultLineColor = Color.Black;
-    private static readonly Color defaultTextColor = Color.Black;
-    private static readonly Color defaultFillColor = Color.White;
-    private const int defaultPreferredWidth = 70;
-    private const int defaultPreferredHeight = 46;
-
-    public VisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) :
-      this(symbolicExpressionTreeNode, defaultLineColor) {
-    }
-
-    public VisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode, Color lineColor) :
-      this(symbolicExpressionTreeNode, lineColor, defaultTextColor) {
-    }
-
-    public VisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode, Color lineColor, Color textColor) :
-      this(symbolicExpressionTreeNode, lineColor, textColor, defaultFillColor) {
-    }
-
-    public VisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode, Color lineColor, Color textColor, Color fillColor) :
-      this(symbolicExpressionTreeNode, lineColor, textColor, fillColor, defaultPreferredWidth, defaultPreferredHeight) {
-    }
-
-    public VisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode, Color lineColor, Color textColor, Color fillColor, int width, int height) {
-      this.symbolicExpressionTreeNode = symbolicExpressionTreeNode;
-      this.lineColor = lineColor;
-      this.textColor = textColor;
-      this.fillColor = fillColor;
-      this.preferredWidth = width;
-      this.preferredHeight = height;
-      this.ToolTip = symbolicExpressionTreeNode.ToString();
-    }
-
-    #region members for internal use only
-    private int x;
-    public int X {
-      get { return x; }
-      internal set { this.x = value; }
-    }
-
-    private int y;
-    public int Y {
-      get { return y; }
-      internal set { this.y = value; }
-    }
-
-    private int width;
-    public int Width {
-      get { return this.width; }
-      internal set { this.width = value; }
-    }
-
-    private int height;
-    public int Height {
-      get { return this.height; }
-      internal set { this.height = value; }
-    }
-    #endregion
-
-    private ISymbolicExpressionTreeNode symbolicExpressionTreeNode;
-    public ISymbolicExpressionTreeNode SymbolicExpressionTreeNode {
-      get { return this.symbolicExpressionTreeNode; }
-      set {
-        symbolicExpressionTreeNode = value;
-        ToolTip = SymbolicExpressionTreeNode.ToString();
-      }
-    }
-
-    private int preferredWidth;
-    public int PreferredWidth {
-      get { return this.preferredWidth; }
-      set { this.preferredWidth = value; }
-    }
-
-    private int preferredHeight;
-    public int PreferredHeight {
-      get { return this.preferredHeight; }
-      set { this.preferredHeight = value; }
-    }
-
-    private Color lineColor;
-    public Color LineColor {
-      get { return this.lineColor; }
-      set { this.lineColor = value; }
-    }
-
-    private Color textColor;
-    public Color TextColor {
-      get { return this.textColor; }
-      set { this.textColor = value; }
-    }
-
-    private Color fillColor;
-    public Color FillColor {
-      get { return this.fillColor; }
-      set { this.fillColor = value; }
-    }
-
-    private string toolTip;
-    public string ToolTip {
-      get { return toolTip; }
-      set { toolTip = value; }
-    }
-  }
-}
Index: able/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualSymbolicExpressionTreeNodeConnection.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualSymbolicExpressionTreeNodeConnection.cs	(revision 11119)
+++ 	(revision )
@@ -1,48 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2013 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.Drawing.Drawing2D;
-
-namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
-  public class VisualSymbolicExpressionTreeNodeConnection : object {
-    private static readonly Color defaultLineColor = Color.Black;
-    private static readonly DashStyle defaultDashStyle = DashStyle.Solid;
-
-    private Color lineColor;
-    public Color LineColor {
-      get { return lineColor; }
-      set { lineColor = value; }
-    }
-
-    private DashStyle dashStyle;
-    public DashStyle DashStyle {
-      get { return dashStyle; }
-      set { dashStyle = value; }
-    }
-
-    public VisualSymbolicExpressionTreeNodeConnection()
-      : base() {
-      lineColor = defaultLineColor;
-      dashStyle = defaultDashStyle;
-    }
-  }
-}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNode.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNode.cs	(revision 11120)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNode.cs	(revision 11120)
@@ -0,0 +1,129 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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;
+
+namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
+  public class VisualTreeNode<T> where T : class {
+    private static readonly Color defaultLineColor = Color.Black;
+    private static readonly Color defaultTextColor = Color.Black;
+    private static readonly Color defaultFillColor = Color.White;
+    private const int defaultPreferredWidth = 70;
+    private const int defaultPreferredHeight = 46;
+
+    public VisualTreeNode(T content) :
+      this(content, defaultLineColor) {
+    }
+
+    public VisualTreeNode(T content, Color lineColor) :
+      this(content, lineColor, defaultTextColor) {
+    }
+
+    public VisualTreeNode(T content, Color lineColor, Color textColor) :
+      this(content, lineColor, textColor, defaultFillColor) {
+    }
+
+    public VisualTreeNode(T content, Color lineColor, Color textColor, Color fillColor) :
+      this(content, lineColor, textColor, fillColor, defaultPreferredWidth, defaultPreferredHeight) {
+    }
+
+    public VisualTreeNode(T content, Color lineColor, Color textColor, Color fillColor, int width, int height) {
+      this.content = content;
+      this.lineColor = lineColor;
+      this.textColor = textColor;
+      this.fillColor = fillColor;
+      this.preferredWidth = width;
+      this.preferredHeight = height;
+      this.ToolTip = content.ToString();
+    }
+
+    #region members for internal use only
+    private int x;
+    public int X {
+      get { return x; }
+      internal set { this.x = value; }
+    }
+
+    private int y;
+    public int Y {
+      get { return y; }
+      internal set { this.y = value; }
+    }
+
+    private int width;
+    public int Width {
+      get { return this.width; }
+      internal set { this.width = value; }
+    }
+
+    private int height;
+    public int Height {
+      get { return this.height; }
+      internal set { this.height = value; }
+    }
+    #endregion
+
+    private T content;
+    public T Content {
+      get { return this.content; }
+      set {
+        content = value;
+        ToolTip = Content.ToString();
+      }
+    }
+
+    private int preferredWidth;
+    public int PreferredWidth {
+      get { return this.preferredWidth; }
+      set { this.preferredWidth = value; }
+    }
+
+    private int preferredHeight;
+    public int PreferredHeight {
+      get { return this.preferredHeight; }
+      set { this.preferredHeight = value; }
+    }
+
+    private Color lineColor;
+    public Color LineColor {
+      get { return this.lineColor; }
+      set { this.lineColor = value; }
+    }
+
+    private Color textColor;
+    public Color TextColor {
+      get { return this.textColor; }
+      set { this.textColor = value; }
+    }
+
+    private Color fillColor;
+    public Color FillColor {
+      get { return this.fillColor; }
+      set { this.fillColor = value; }
+    }
+
+    private string toolTip;
+    public string ToolTip {
+      get { return toolTip; }
+      set { toolTip = value; }
+    }
+  }
+}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNodeConnection.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNodeConnection.cs	(revision 11120)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNodeConnection.cs	(revision 11120)
@@ -0,0 +1,48 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2013 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.Drawing.Drawing2D;
+
+namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
+  public class VisualTreeNodeConnection {
+    private static readonly Color defaultLineColor = Color.Black;
+    private static readonly DashStyle defaultDashStyle = DashStyle.Solid;
+
+    private Color lineColor;
+    public Color LineColor {
+      get { return lineColor; }
+      set { lineColor = value; }
+    }
+
+    private DashStyle dashStyle;
+    public DashStyle DashStyle {
+      get { return dashStyle; }
+      set { dashStyle = value; }
+    }
+
+    public VisualTreeNodeConnection()
+      : base() {
+      lineColor = defaultLineColor;
+      dashStyle = defaultDashStyle;
+    }
+  }
+}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Formatters/SymbolicExpressionTreeHierarchicalFormatter.cs
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Formatters/SymbolicExpressionTreeHierarchicalFormatter.cs	(revision 11120)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Formatters/SymbolicExpressionTreeHierarchicalFormatter.cs	(revision 11120)
@@ -0,0 +1,93 @@
+﻿#region License Information
+
+/* HeuristicLab
+ * Copyright (C) 2002-2014 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.IO;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
+  [Item("Hierarchical Formatter", "Formatter for symbolic expression trees that uses special characters for drawing a tree in text-mode.")]
+  public sealed class SymbolicExpressionTreeHierarchicalFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
+    private SymbolicExpressionTreeHierarchicalFormatter(SymbolicExpressionTreeHierarchicalFormatter original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicExpressionTreeHierarchicalFormatter(this, cloner);
+    }
+
+    public SymbolicExpressionTreeHierarchicalFormatter() :
+      base("Hierarchical Formatter", "Formatter for symbolic expression trees that uses special characters for drawing a tree in text-mode.") { }
+
+    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
+      var sw = new StringWriter();
+      RenderTree(sw, symbolicExpressionTree);
+      return sw.ToString();
+    }
+
+    private static void RenderTree(TextWriter writer, ISymbolicExpressionTree tree) {
+      RenderNode(writer, tree.Root, string.Empty);
+    }
+
+    public static void RenderNode(TextWriter writer, ISymbolicExpressionTreeNode node, string prefix) {
+      string label = node.ToString();
+      writer.Write(label);
+      if (node.SubtreeCount > 0) {
+        var padding = prefix + new string(' ', label.Length);
+        for (int i = 0; i != node.SubtreeCount; ++i) {
+          char connector, extender = ' ';
+          if (i == 0) {
+            if (node.SubtreeCount > 1) {
+              connector = RenderChars.JunctionDown;
+              extender = RenderChars.VerticalLine;
+            } else {
+              connector = RenderChars.HorizontalLine;
+              extender = ' ';
+            }
+          } else {
+            writer.Write(padding);
+            if (i == node.SubtreeCount - 1) {
+              connector = RenderChars.CornerRight;
+              extender = ' ';
+            } else {
+              connector = RenderChars.JunctionRight;
+              extender = RenderChars.VerticalLine;
+            }
+          }
+          writer.Write(string.Concat(connector, RenderChars.HorizontalLine));
+          var newPrefix = string.Concat(padding, extender, ' ');
+          RenderNode(writer, node.GetSubtree(i), newPrefix);
+        }
+      } else
+        writer.WriteLine();
+    }
+
+    // helper class providing characters for displaying a tree in the console
+    public static class RenderChars {
+      public const char JunctionDown = '┬';
+      public const char HorizontalLine = '─';
+      public const char VerticalLine = '│';
+      public const char JunctionRight = '├';
+      public const char CornerRight = '└';
+    }
+  }
+}
Index: /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj
===================================================================
--- /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj	(revision 11119)
+++ /stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj	(revision 11120)
@@ -135,4 +135,5 @@
     <Compile Include="Creators\RampedHalfAndHalfTreeCreator.cs" />
     <Compile Include="Formatters\SymbolicExpressionTreeGraphvizFormatter.cs" />
+    <Compile Include="Formatters\SymbolicExpressionTreeHierarchicalFormatter.cs" />
     <Compile Include="Interfaces\IReadOnlySymbol.cs" />
     <Compile Include="Interfaces\ISymbolicExpressionGrammar.cs" />
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 11119)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs	(revision 11120)
@@ -52,4 +52,5 @@
       Content.ModelChanged += Content_Changed;
       Content.ProblemDataChanged += Content_Changed;
+      treeChart.Repainted += treeChart_Repainted;
     }
     protected override void DeregisterContentEvents() {
@@ -57,4 +58,5 @@
       Content.ModelChanged -= Content_Changed;
       Content.ProblemDataChanged -= Content_Changed;
+      treeChart.Repainted -= treeChart_Repainted;
     }
 
@@ -68,4 +70,9 @@
       UpdateView();
       viewHost.Content = this.Content;
+    }
+
+    private void treeChart_Repainted(object sender, EventArgs e) {
+      if (nodeImpacts != null && nodeImpacts.Count > 0)
+        PaintNodeImpacts();
     }
 
@@ -96,21 +103,18 @@
 
     private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
-      var visualNode = (VisualSymbolicExpressionTreeNode)sender;
-      var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.SymbolicExpressionTreeNode;
-      if (symbExprTreeNode == null) return;
-      var tree = Content.Model.SymbolicExpressionTree;
+      var visualNode = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender;
+      if (visualNode.Content == null) { throw new Exception("Visual node content cannot be null."); }
+      var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.Content;
+      if (!foldedNodes.ContainsKey(symbExprTreeNode)) return; // constant nodes cannot be folded
       var parent = symbExprTreeNode.Parent;
       int indexOfSubtree = parent.IndexOfSubtree(symbExprTreeNode);
-      if (foldedNodes.ContainsKey(symbExprTreeNode)) {
-        // undo node folding
-        SwitchNodeWithReplacementNode(parent, indexOfSubtree);
-      }
-      UpdateModel(tree);
+      SwitchNodeWithReplacementNode(parent, indexOfSubtree);
+      UpdateModel(Content.Model.SymbolicExpressionTree);
     }
 
     private void SwitchNodeWithReplacementNode(ISymbolicExpressionTreeNode parent, int subTreeIndex) {
       ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex);
-      parent.RemoveSubtree(subTreeIndex);
       if (foldedNodes.ContainsKey(subTree)) {
+        parent.RemoveSubtree(subTreeIndex);
         var replacementNode = foldedNodes[subTree];
         parent.InsertSubtree(subTreeIndex, replacementNode);
@@ -125,8 +129,9 @@
       double max = impacts.Max();
       double min = impacts.Min();
-      foreach (ISymbolicExpressionTreeNode treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
-        VisualSymbolicExpressionTreeNode visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
+      foreach (var treeNode in Content.Model.SymbolicExpressionTree.IterateNodesPostfix()) {
+        VisualTreeNode<ISymbolicExpressionTreeNode> visualTree = treeChart.GetVisualSymbolicExpressionTreeNode(treeNode);
 
         if (!(treeNode is ConstantTreeNode) && nodeImpacts.ContainsKey(treeNode)) {
+          visualTree.ToolTip = visualTree.Content.ToString(); // to avoid duplicate tooltips
           double impact = nodeImpacts[treeNode];
 
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.cs	(revision 11119)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.cs	(revision 11120)
@@ -33,5 +33,5 @@
   internal sealed partial class InteractiveSymbolicExpressionTreeChart : SymbolicExpressionTreeChart {
     private ISymbolicExpressionTreeNode tempNode; // node in clipboard (to be cut/copy/pasted etc)
-    private VisualSymbolicExpressionTreeNode currSelected; // currently selected node
+    private VisualTreeNode<ISymbolicExpressionTreeNode> currSelected; // currently selected node
     private enum EditOp { NoOp, CopySubtree, CutSubtree }
     private EditOp lastOp = EditOp.NoOp;
@@ -65,5 +65,5 @@
         pasteToolStripMenuItem.Visible = false;
       } else {
-        var node = currSelected.SymbolicExpressionTreeNode;
+        var node = currSelected.Content;
         insertNodeToolStripMenuItem.Visible = true;
         changeNodeToolStripMenuItem.Visible = true;
@@ -77,10 +77,10 @@
         pasteToolStripMenuItem.Enabled = tempNode != null && insertNodeToolStripMenuItem.Enabled
                                                           && !(lastOp == EditOp.CutSubtree
-                                                               && tempNode.IterateNodesBreadth().Contains(currSelected.SymbolicExpressionTreeNode));
+                                                               && tempNode.IterateNodesBreadth().Contains(currSelected.Content));
       }
     }
 
     protected override void OnSymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
-      currSelected = (VisualSymbolicExpressionTreeNode)sender; ;
+      currSelected = (VisualTreeNode<ISymbolicExpressionTreeNode>)sender; ;
       if (currSelected != null) {
         currSelected.LineColor = Color.FromArgb(130, currSelected.LineColor);
@@ -104,6 +104,6 @@
 
     private void insertNodeToolStripMenuItem_Click(object sender, EventArgs e) {
-      if (currSelected == null || currSelected.SymbolicExpressionTreeNode is SymbolicExpressionTreeTerminalNode) return;
-      var parent = currSelected.SymbolicExpressionTreeNode;
+      if (currSelected == null || currSelected.Content is SymbolicExpressionTreeTerminalNode) return;
+      var parent = currSelected.Content;
 
       using (var dialog = new InsertNodeDialog()) {
@@ -138,6 +138,6 @@
       if (currSelected == null) return;
 
-      var node = (ISymbolicExpressionTreeNode)currSelected.SymbolicExpressionTreeNode.Clone();
-      var originalNode = currSelected.SymbolicExpressionTreeNode;
+      var node = (ISymbolicExpressionTreeNode)currSelected.Content.Clone();
+      var originalNode = currSelected.Content;
 
       ISymbolicExpressionTreeNode newNode = null;
@@ -180,5 +180,5 @@
         }
       }
-      tempNode = currSelected.SymbolicExpressionTreeNode;
+      tempNode = currSelected.Content;
       foreach (var node in tempNode.IterateNodesPostfix()) {
         var visualNode = GetVisualSymbolicExpressionTreeNode(node);
@@ -194,5 +194,5 @@
     }
     private void removeNodeToolStripMenuItem_Click(object sender, EventArgs e) {
-      var node = currSelected.SymbolicExpressionTreeNode;
+      var node = currSelected.Content;
       if (node == tempNode) tempNode = null;
       ModifyTree(Tree, node.Parent, node, null, removeSubtree: false);
@@ -200,5 +200,5 @@
     }
     private void removeSubtreeToolStripMenuItem_Click(object sender, EventArgs e) {
-      var node = currSelected.SymbolicExpressionTreeNode;
+      var node = currSelected.Content;
       if (node.IterateNodesPostfix().Contains(tempNode)) tempNode = null;
       ModifyTree(Tree, node.Parent, node, null, removeSubtree: true);
@@ -209,5 +209,5 @@
       if (!(lastOp == EditOp.CopySubtree || lastOp == EditOp.CutSubtree)) return;
       // check if the copied/cut node (stored in the tempNode) can be inserted as a child of the current selected node
-      var node = currSelected.SymbolicExpressionTreeNode;
+      var node = currSelected.Content;
       if (node is ConstantTreeNode || node is VariableTreeNode) return;
       // check if the currently selected node can accept the copied node as a child 
@@ -218,5 +218,5 @@
             if (tempNode.IterateNodesBreadth().Contains(node))
               throw new ArgumentException();// cannot cut/paste a node into itself
-            ModifyTree(Tree, tempNode.Parent, tempNode, null); //remove node from its original parent 	 	 
+            ModifyTree(Tree, tempNode.Parent, tempNode, null); //remove node from its original parent
             ModifyTree(Tree, node, null, tempNode); //insert it as a child to the new parent 
             break;
Index: /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/TextualSymbolicDataAnalysisModelView.designer.cs
===================================================================
--- /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/TextualSymbolicDataAnalysisModelView.designer.cs	(revision 11119)
+++ /stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/TextualSymbolicDataAnalysisModelView.designer.cs	(revision 11120)
@@ -48,5 +48,5 @@
       this.SuspendLayout();
       // 
-      // expressionTreeView
+      // symbolicExpressionTreeView
       // 
       this.symbolicExpressionTreeView.AllowDrop = true;
@@ -55,16 +55,15 @@
       this.symbolicExpressionTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
       this.symbolicExpressionTreeView.Location = new System.Drawing.Point(0, 0);
-      this.symbolicExpressionTreeView.Name = "expressionTreeView";
+      this.symbolicExpressionTreeView.Name = "symbolicExpressionTreeView";
       this.symbolicExpressionTreeView.ReadOnly = false;
       this.symbolicExpressionTreeView.Size = new System.Drawing.Size(352, 413);
       this.symbolicExpressionTreeView.TabIndex = 0;
       // 
-      // SymbolicExpressionModelView
+      // TextualSymbolicDataAnalysisModelView
       // 
       this.AllowDrop = true;
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
       this.Controls.Add(this.symbolicExpressionTreeView);
-      this.Name = "SymbolicExpressionModelView";
+      this.Name = "TextualSymbolicDataAnalysisModelView";
       this.Size = new System.Drawing.Size(352, 413);
       this.ResumeLayout(false);
