diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin
index e90edc33e1..9319ba1da9 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin
@@ -149,4 +149,13 @@
class = "ICSharpCode.SharpDevelop.Gui.OptionPanels.DebuggingSymbolsPanel"/>
+
+
+
+
+
+
+
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
index e3ea509420..4fe7b61ce3 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
@@ -19,7 +19,7 @@
4096
false
Always
- v3.0
+ v3.5
"C:\Program Files\SharpDevelop\3.0\bin\..\AddIns\AddIns\Misc\SourceAnalysis\Settings.SourceAnalysis"
C:\Dokumente und Einstellungen\HP\Anwendungsdaten\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis
http://localhost/Debugger.AddIn/
@@ -62,7 +62,13 @@
3.0
+
+ 3.0
+
+
+ 3.5
+
@@ -140,6 +146,7 @@
EditBreakpointScriptForm.cs
+
Configuration\GlobalAssemblyInfo.cs
@@ -160,6 +167,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -223,6 +257,15 @@
ICSharpCode.Core.WinForms
False
+
+
+
+
+
+
+
+
+
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/DebuggerVisualizerException.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/DebuggerVisualizerException.cs
new file mode 100644
index 0000000000..cc86d867f2
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/DebuggerVisualizerException.cs
@@ -0,0 +1,31 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Description of DebuggerVisualizerException.
+ ///
+ public class DebuggerVisualizerException : ApplicationException
+ {
+ public DebuggerVisualizerException()
+ : base()
+ {
+ }
+
+ public DebuggerVisualizerException(string message)
+ : base(message)
+ {
+ }
+
+ public DebuggerVisualizerException(string message, System.Exception innerException)
+ : base(message, innerException)
+ {
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/GraphDrawer.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/GraphDrawer.cs
new file mode 100644
index 0000000000..14610089d7
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/GraphDrawer.cs
@@ -0,0 +1,43 @@
+using System;
+//
+//
+//
+//
+// $Revision$
+//
+using System.Collections.Generic;
+using System.Text;
+using Debugger.AddIn.Visualizers.Graph;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows;
+using Debugger.AddIn.Visualizers.Graph.Drawing;
+using Debugger.AddIn.Visualizers.Graph.Layout;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Draws ObjectGraph on a Canvas.
+ ///
+ public class GraphDrawer
+ {
+ private ObjectGraph graph;
+
+ public GraphDrawer(ObjectGraph graph)
+ {
+ this.graph = graph;
+ }
+
+ public static void Draw(PositionedGraph posGraph, Canvas canvas)
+ {
+ canvas.Children.Clear();
+
+ foreach (PositionedNode node in posGraph.Nodes)
+ {
+ canvas.Children.Add(node.NodeVisualControl);
+ Canvas.SetLeft(node.NodeVisualControl, node.Left);
+ Canvas.SetTop(node.NodeVisualControl, node.Top);
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml
new file mode 100644
index 0000000000..e135828cca
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml.cs
new file mode 100644
index 0000000000..165fafea46
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml.cs
@@ -0,0 +1,78 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Debugger.AddIn.Visualizers.Graph;
+
+namespace Debugger.AddIn.Visualizers.Graph.Drawing
+{
+ ///
+ /// UserControl used to display ObjectNode.
+ ///
+ public partial class NodeControl : UserControl
+ {
+ public NodeControl()
+ {
+ InitializeComponent();
+ }
+
+ private ObjectNode node;
+ ///
+ /// ObjectNode that this control displays.
+ ///
+ public ObjectNode GraphNode
+ {
+ get
+ {
+ return node;
+ }
+ set
+ {
+ node = value;
+ int row = 0;
+ // dynamically create TextBlocks and insert them to the 2-column propertyGrid
+ foreach (var property in node.Properties)
+ {
+ propertyGrid.RowDefinitions.Add(new RowDefinition());
+
+ TextBlock txtName = createTextBlock(property.Name);
+ propertyGrid.Children.Add(txtName);
+ Grid.SetRow(txtName, row);
+ Grid.SetColumn(txtName, 0);
+
+ TextBlock txtValue = createTextBlock(property.Value);
+ propertyGrid.Children.Add(txtValue);
+ Grid.SetRow(txtValue, row);
+ Grid.SetColumn(txtValue, 1);
+
+ row++;
+ }
+ }
+ }
+
+ ///
+ /// Creates TextBlock with given text.
+ ///
+ private TextBlock createTextBlock(string text)
+ {
+ TextBlock newTextblock = new TextBlock();
+ newTextblock.Text = text;
+ newTextblock.Padding = new Thickness(4);
+ return newTextblock;
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedEdge.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedEdge.cs
new file mode 100644
index 0000000000..1480f03264
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedEdge.cs
@@ -0,0 +1,17 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Edge with position information.
+ ///
+ public class PositionedEdge : NamedEdge
+ {
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraph.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraph.cs
new file mode 100644
index 0000000000..df8eec8431
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraph.cs
@@ -0,0 +1,44 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Graph with positioned nodes and edges.
+ ///
+ public class PositionedGraph
+ {
+ internal List nodes = new List();
+
+ ///
+ /// All nodes in the graph.
+ ///
+ public IEnumerable Nodes
+ {
+ get { return nodes; }
+ }
+
+ ///
+ /// All edges in the graph.
+ ///
+ public IEnumerable Edges
+ {
+ get
+ {
+ foreach (PositionedNode node in this.Nodes)
+ {
+ foreach (PositionedEdge edge in node.Edges)
+ {
+ yield return edge;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs
new file mode 100644
index 0000000000..cdbe66a642
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs
@@ -0,0 +1,54 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using Debugger.AddIn.Visualizers.Graph.Drawing;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Node with position information.
+ ///
+ public class PositionedNode
+ {
+ public PositionedNode(NodeControl nodeVisualControl)
+ {
+ this.nodeVisualControl = nodeVisualControl;
+ }
+
+ public double Left { get; set; }
+ public double Top { get; set; }
+ public double Width
+ {
+ get { return NodeVisualControl.DesiredSize.Width; }
+ }
+ public double Height
+ {
+ get { return NodeVisualControl.DesiredSize.Height; }
+ }
+
+ private NodeControl nodeVisualControl;
+ ///
+ /// Visual control to be shown for this node.
+ ///
+ public NodeControl NodeVisualControl
+ {
+ get
+ {
+ return this.nodeVisualControl;
+ }
+ }
+
+ public virtual IEnumerable Edges
+ {
+ get
+ {
+ return new PositionedEdge[]{};
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/LayoutDirection.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/LayoutDirection.cs
new file mode 100644
index 0000000000..0c09ac6313
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/LayoutDirection.cs
@@ -0,0 +1,19 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Direction of tree layout.
+ ///
+ public enum LayoutDirection
+ {
+ TopBottom,
+ LeftRight
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeEdge.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeEdge.cs
new file mode 100644
index 0000000000..ae7f156e1d
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeEdge.cs
@@ -0,0 +1,17 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Description of TreeEdge.
+ ///
+ public class TreeEdge : PositionedEdge
+ {
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs
new file mode 100644
index 0000000000..77685bd344
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs
@@ -0,0 +1,122 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using Debugger.AddIn.Visualizers.Graph.Drawing;
+using System.Linq;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Calculates layout of , producing .
+ ///
+ public class TreeLayouter
+ {
+ private static readonly double horizNodeMargin = 20;
+ private static readonly double vertNodeMargin = 20;
+
+ private LayoutDirection layoutDirection = LayoutDirection.TopBottom;
+
+ PositionedGraph resultGraph = null;
+
+ Dictionary treeNodeFor = new Dictionary();
+ Dictionary seenNodes = new Dictionary();
+
+ public TreeLayouter()
+ {
+ }
+
+ private TreeNode createTreeNode(NodeControl nodeVisualControl)
+ {
+ return TreeNode.Create(this.layoutDirection, nodeVisualControl);
+ }
+
+ ///
+ /// Calculates layout for given .
+ ///
+ ///
+ ///
+ public PositionedGraph CalculateLayout(ObjectGraph objectGraph, LayoutDirection direction)
+ {
+ resultGraph = new PositionedGraph();
+ layoutDirection = direction;
+
+ var seenNodes = new Dictionary();
+
+ TreeNode tree = buildTreeRecursive(objectGraph.Root);
+ calculateNodePosRecursive(tree, 0, 0);
+
+ return resultGraph;
+ }
+
+ private TreeNode buildTreeRecursive(ObjectNode objectGraphNode)
+ {
+ seenNodes.Add(objectGraphNode, null);
+
+ NodeControl nodeVisualControl = new NodeControl();
+ nodeVisualControl.GraphNode = objectGraphNode;
+ nodeVisualControl.Measure(new Size(500, 500));
+
+ TreeNode newTreeNode = createTreeNode(nodeVisualControl);
+ newTreeNode.HorizontalMargin = horizNodeMargin;
+ newTreeNode.VerticalMargin = vertNodeMargin;
+ resultGraph.nodes.Add(newTreeNode);
+ treeNodeFor[objectGraphNode] = newTreeNode;
+
+ double subtreeSize = 0;
+ foreach (ObjectEdge edge in objectGraphNode.Edges)
+ {
+ ObjectNode neighbor = edge.TargetNode;
+ if (seenNodes.ContainsKey(neighbor))
+ {
+ newTreeNode.AdditionalNeighbors.Add(new TreeEdge { Name = edge.Name, SourceNode = newTreeNode, TargetNode = treeNodeFor[neighbor]});
+ }
+ else
+ {
+ TreeNode newChild = buildTreeRecursive(neighbor);
+ newTreeNode.ChildEdges.Add(new TreeEdge { Name = edge.Name, SourceNode = newTreeNode, TargetNode = newChild});
+
+ subtreeSize += newChild.SubtreeSize;
+ }
+ }
+ subtreeSize = Math.Max(newTreeNode.LateralSize + newTreeNode.LateralMargin, subtreeSize);
+ newTreeNode.SubtreeSize = subtreeSize;
+
+ return newTreeNode;
+ }
+
+ ///
+ /// Given SubtreeSize for each node, positions the nodes, in a left-to-right or top-to-bottom fashion.
+ ///
+ ///
+ ///
+ ///
+ private void calculateNodePosRecursive(TreeNode node, double lateralStart, double mainStart)
+ {
+ // center this node
+ double subtreeSize = node.Childs.Sum(child => child.SubtreeSize);
+ double center = node.Childs.Count() == 0 ? 0 : 0.5 * (subtreeSize - (node.LateralSize + node.LateralMargin));
+
+ // design alternatives
+ // node.MainPos += center; // used this
+ // Adapt(node).PosLateral += center; // TreeNodeAdapterLR + TreeNodeAdapterTB
+ // SetMainPos(node, GetMainPos(node) + 10) // TreeNodeAdapterLR + TreeNodeAdapterTB, no creation
+
+ node.LateralCoord += lateralStart + center;
+ node.MainCoord = mainStart;
+
+ double childLateral = lateralStart;
+ double childsMainFixed = node.MainCoord + node.MainSize + node.MainMargin;
+ foreach (TreeNode child in node.Childs)
+ {
+ calculateNodePosRecursive(child, childLateral, childsMainFixed);
+ childLateral += child.SubtreeSize;
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNode.cs
new file mode 100644
index 0000000000..4be7d73e92
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNode.cs
@@ -0,0 +1,89 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using Debugger.AddIn.Visualizers.Graph.Drawing;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Abstract ancestor of TreeNodeLR and TreeNodeTB.
+ /// There are 2 dimensions - "main" and "lateral".
+ /// Main dimension is the dimension in which the graph depth grows (vertical when TB, horizontal when LR).
+ /// Lateral dimension is the other dimension. Siblings are placed next to each other in Lateral dimension.
+ ///
+ public abstract class TreeNode : PositionedNode
+ {
+ public static TreeNode Create(LayoutDirection direction, NodeControl nodeVisualControl)
+ {
+ switch (direction) {
+ case LayoutDirection.TopBottom: return new TreeNodeTB(nodeVisualControl);
+ case LayoutDirection.LeftRight: return new TreeNodeLR(nodeVisualControl);
+ default: throw new DebuggerVisualizerException("Unsupported layout direction: " + direction.ToString());
+ }
+ }
+
+ public double HorizontalMargin { get; set; }
+ public double VerticalMargin { get; set; }
+
+ protected TreeNode(NodeControl nodeVisualControl) : base(nodeVisualControl)
+ {
+ }
+
+ ///
+ /// Width or height of the subtree.
+ ///
+ public double SubtreeSize { get; set; }
+
+ public abstract double MainCoord { get; set; }
+ public abstract double LateralCoord { get; set; }
+
+ public abstract double MainSize { get; }
+ public abstract double LateralSize { get; }
+
+ public abstract double MainMargin { get; }
+ public abstract double LateralMargin { get; }
+
+ private List childs = new List();
+ public List ChildEdges
+ {
+ get
+ {
+ return childs;
+ }
+ }
+
+ public IEnumerable Childs
+ {
+ get
+ {
+ foreach (TreeEdge childEdge in ChildEdges)
+ yield return (TreeNode)childEdge.TargetNode;
+ }
+ }
+
+ private List additionalNeighbors = new List();
+ public List AdditionalNeighbors
+ {
+ get
+ {
+ return additionalNeighbors;
+ }
+ }
+
+ public override IEnumerable Edges
+ {
+ get
+ {
+ foreach (TreeEdge childEdge in ChildEdges)
+ yield return childEdge;
+ foreach (TreeEdge neighborEdge in AdditionalNeighbors)
+ yield return neighborEdge;
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeLR.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeLR.cs
new file mode 100644
index 0000000000..50efa075a1
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeLR.cs
@@ -0,0 +1,30 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using Debugger.AddIn.Visualizers.Graph.Drawing;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Description of TreeNodeLR.
+ ///
+ public class TreeNodeLR: TreeNode
+ {
+ public TreeNodeLR(NodeControl nodeControl) : base(nodeControl)
+ {
+ }
+
+ public override double MainSize { get { return this.Width; } }
+ public override double LateralSize { get { return this.Height ; } }
+
+ public override double MainCoord { get { return this.Left; } set { this.Left = value; } }
+ public override double LateralCoord { get { return this.Top; } set { this.Top = value; } }
+
+ public override double MainMargin { get { return this.HorizontalMargin; } }
+ public override double LateralMargin { get { return this.VerticalMargin; } }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeTB.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeTB.cs
new file mode 100644
index 0000000000..5c5a323ed3
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeNodeTB.cs
@@ -0,0 +1,30 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using Debugger.AddIn.Visualizers.Graph.Drawing;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Description of TreeNodeTB.
+ ///
+ public class TreeNodeTB : TreeNode
+ {
+ public TreeNodeTB(NodeControl nodeControl) : base(nodeControl)
+ {
+ }
+
+ public override double MainSize { get { return this.Height; } }
+ public override double LateralSize { get { return this.Width; } }
+
+ public override double MainCoord { get { return this.Top; } set { this.Top = value; } }
+ public override double LateralCoord { get { return this.Left; } set { this.Left = value; } }
+
+ public override double MainMargin { get { return this.VerticalMargin; } }
+ public override double LateralMargin { get { return this.HorizontalMargin; } }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/NamedEdge.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/NamedEdge.cs
new file mode 100644
index 0000000000..8df02d517c
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/NamedEdge.cs
@@ -0,0 +1,38 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Named edge connecting 2 objects of same type.
+ ///
+ public class NamedEdge : NamedEdge
+ {
+ }
+
+ ///
+ /// Named edge connecting 2 objects of arbitrary types.
+ ///
+ public class NamedEdge
+ {
+ ///
+ /// Name of the edge.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Target node of the edge.
+ ///
+ public TTarget TargetNode { get; set; }
+
+ ///
+ /// Source node of the edge.
+ ///
+ public TSource SourceNode { get; set; }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectEdge.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectEdge.cs
new file mode 100644
index 0000000000..2c23e7a38e
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectEdge.cs
@@ -0,0 +1,19 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Named edge in the .
+ ///
+ public class ObjectEdge : NamedEdge
+ {
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs
new file mode 100644
index 0000000000..2a500f853d
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs
@@ -0,0 +1,58 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Object graph built by
+ ///
+ public class ObjectGraph
+ {
+ ///
+ /// Root of the graph.
+ ///
+ public ObjectNode Root { get; internal set; }
+
+ ///
+ /// Adds node to the graph.
+ ///
+ /// node to be added
+ internal void AddNode(ObjectNode node)
+ {
+ _nodes.Add(node);
+ }
+
+ private List _nodes = new List();
+ ///
+ /// All nodes in the graph.
+ ///
+ public IEnumerable Nodes
+ {
+ get { return _nodes; }
+ }
+
+ ///
+ /// All edges in the graph.
+ ///
+ public IEnumerable Edges
+ {
+ get
+ {
+ foreach (ObjectNode node in this.Nodes)
+ {
+ foreach (ObjectEdge edge in node.Edges)
+ {
+ yield return edge;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs
new file mode 100644
index 0000000000..28563667d6
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs
@@ -0,0 +1,259 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using ICSharpCode.SharpDevelop.Services;
+using Debugger;
+using Debugger.MetaData;
+using Debugger.Wrappers.CorDebug;
+using Debugger.Expressions;
+using Debugger.AddIn.Visualizers.Graph.Utils;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ // The object graph building starts with given expression and recursively
+ // explores all its members.
+ //
+ // Important part of the algorithm is finding if we already have a node
+ // for given value - to detect loops and shared references correctly.
+ // This is done using the following algorithm:
+ //
+ // getNodeForValue(value)
+ // get the hashCode for the value
+ // find if there is already a node with this hashCode (in O(1))
+ // if not, we can be sure we have not seen this value yet
+ // if yes, it might be different object with the same hashCode -> compare addresses
+ //
+ // 'different object with the same hashCode' are possible - my question on stackoverflow:
+ // http://stackoverflow.com/questions/750947/-net-unique-object-identifier
+ //
+ // this way, the whole graph building is O(n) in the size of the resulting graph
+ // It tries to call as few Expression.Evaluate as possible, since Expression.Evaluate is expensive (5ms) -
+ // this is a prototype and the speed can be I believe greatly improved for future versions.
+
+ ///
+ /// Builds for given string expression.
+ ///
+ public class ObjectGraphBuilder
+ {
+ ///
+ /// The underlying debugger service used for getting expression values.
+ ///
+ private WindowsDebugger _debuggerService;
+ ///
+ /// The resulting object graph.
+ ///
+ private ObjectGraph _resultGraph;
+
+ ///
+ /// Given hash code, lookup already existing node(s) with this hash code.
+ ///
+ private Lookup objectNodesForHashCode = new Lookup();
+
+ ///
+ /// Binding flags for getting member expressions.
+ ///
+ private readonly Debugger.MetaData.BindingFlags _bindingFlags =
+ BindingFlags.Public | BindingFlags.Instance | BindingFlags.Field | BindingFlags.GetProperty;
+
+ ///
+ /// Creates ObjectGraphBuilder.
+ ///
+ /// Debugger service.
+ public ObjectGraphBuilder(WindowsDebugger debuggerService)
+ {
+ _debuggerService = debuggerService;
+ }
+
+ ///
+ /// Builds full object graph for given string expression.
+ ///
+ /// Expression valid in the program being debugged (eg. variable name)
+ /// Object graph
+ public ObjectGraph BuildGraphForExpression(string expression)
+ {
+ if (string.IsNullOrEmpty(expression))
+ {
+ throw new DebuggerVisualizerException("Expression cannot be empty.");
+ }
+
+ _resultGraph = new ObjectGraph();
+
+ // empty graph for null expression
+ if (!_debuggerService.GetValueFromName(expression).IsNull)
+ {
+ _resultGraph.Root = buildGraphRecursive(_debuggerService.GetValueFromName(expression).GetPermanentReference());
+ }
+
+ return _resultGraph;
+ }
+
+ ///
+ /// Builds the subgraph representing given value.
+ ///
+ /// The Value for which the subgraph will be built.
+ /// ObjectNode representing the value + all recursive members.
+ private ObjectNode buildGraphRecursive(Value rootValue)
+ {
+ ObjectNode thisNode = createNewNode(rootValue);
+
+ /*string[] memberValues = rootValue.GetMemberValuesAsString(_bindingFlags);
+ foreach (string memberValue in memberValues)
+ {
+ //Value memberValuePerm = memberValue.GetPermanentReference();
+
+ }*/
+
+
+ foreach(Expression memberExpr in rootValue.Expression.AppendObjectMembers(rootValue.Type, _bindingFlags))
+ {
+ checkIsOfSupportedType(memberExpr);
+
+ string memberName = memberExpr.CodeTail;
+ if (isOfAtomicType(memberExpr))
+ {
+ // atomic members are added to the list of node's "properties"
+ string memberValueAsString = memberExpr.Evaluate(_debuggerService.DebuggedProcess).AsString;
+ thisNode.AddProperty(memberName, memberValueAsString);
+ }
+ else
+ {
+ if (!isNull(memberExpr))
+ {
+ // for object members, edges are added
+
+ Value memberValue = getPermanentReference(memberExpr);
+
+ // if node for memberValue already exists, only add edge to it (so loops etc. are solved correctly)
+ ObjectNode targetNode = getNodeForValue(memberValue);
+ if (targetNode == null)
+ {
+ // if no node for memberValue exists, build the subgraph for the value
+ targetNode = buildGraphRecursive(memberValue);
+ }
+ // add the edge
+ thisNode.AddNamedEdge(targetNode, memberName);
+ }
+ }
+ }
+
+ return thisNode;
+ }
+
+ ///
+ /// Creates new node for the value.
+ ///
+ /// Value, has to be valid.
+ /// New empty object node representing the value.
+ private ObjectNode createNewNode(Value permanentReference)
+ {
+ ObjectNode newNode = new ObjectNode();
+
+ _resultGraph.AddNode(newNode);
+ // remember this node's hashcode for quick lookup
+ objectNodesForHashCode.Add(invokeGetHashCode(permanentReference), newNode);
+
+ // permanent reference to the object this node represents is useful for graph building,
+ // and matching nodes in animations
+ newNode.PermanentReference = permanentReference;
+
+ return newNode;
+ }
+
+ ///
+ /// Finds node that represents the same instance as given value.
+ ///
+ /// Valid value representing an instance.
+ ///
+ private ObjectNode getNodeForValue(Value value)
+ {
+ string objectHashCode = invokeGetHashCode(value);
+ // are there any nodes with the same hash code?
+ LookupValueCollection nodesWithSameHashCode = objectNodesForHashCode[objectHashCode];
+ if (nodesWithSameHashCode == null)
+ {
+ return null;
+ }
+ else
+ {
+ // if there is a node with same hash code, check if it has also the same address
+ // (hash codes are not uniqe - http://stackoverflow.com/questions/750947/-net-unique-object-identifier)
+ ulong objectAddress = getObjectValue(value);
+ ObjectNode nodeWithSameAddress = nodesWithSameHashCode.Find(
+ node => { return objectAddress == getObjectValue(node.PermanentReference); } );
+ return nodeWithSameAddress;
+ }
+ }
+
+ ///
+ /// Invokes GetHashCode on given value.
+ ///
+ /// Valid value.
+ /// Hash code of the object in the debugee.
+ private string invokeGetHashCode(Value value)
+ {
+ MethodInfo method = value.Type.GetMember("GetHashCode", BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo;
+ string hashCode = value.InvokeMethod(method, null).AsString;
+ return hashCode;
+ }
+
+ ///
+ /// Checks whether given expression's type is supported by the graph builder.
+ ///
+ /// Expression to be checked.
+ private void checkIsOfSupportedType(Expression expr)
+ {
+ DebugType typeOfValue = expr.Evaluate(_debuggerService.DebuggedProcess).Type;
+ if (typeOfValue.IsArray)
+ {
+ // arrays will be supported of course in the final version
+ throw new DebuggerVisualizerException("Arrays are not supported yet");
+ }
+ }
+
+ ///
+ /// Checks whether given expression's type is atomic - atomic values will be added to node's property list.
+ ///
+ /// Expression.
+ /// True if expression's type is atomic, False otherwise.
+ private bool isOfAtomicType(Expression expr)
+ {
+ DebugType typeOfValue = expr.Evaluate(_debuggerService.DebuggedProcess).Type;
+ return (!typeOfValue.IsClass) || typeOfValue.IsString;
+ }
+
+ #region helpers
+
+ private Value getPermanentReference(Expression expr)
+ {
+ return expr.Evaluate(_debuggerService.DebuggedProcess).GetPermanentReference();
+ }
+
+ private bool isNull(Expression expr)
+ {
+ return expr.Evaluate(_debuggerService.DebuggedProcess).IsNull;
+ }
+
+ private DebugType getType(Expression expr)
+ {
+ return expr.Evaluate(_debuggerService.DebuggedProcess).Type;
+ }
+
+ private ulong getObjectAddress(Expression expr)
+ {
+ return getObjectValue(expr.Evaluate(_debuggerService.DebuggedProcess));
+ }
+
+ private ulong getObjectValue(Value val)
+ {
+ ICorDebugReferenceValue refVal = val.CorValue.CastTo();
+ return refVal.Value;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectNode.cs
new file mode 100644
index 0000000000..886598322a
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectNode.cs
@@ -0,0 +1,57 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Node in the .
+ ///
+ public class ObjectNode
+ {
+ ///
+ /// Additional info useful for internal algorithms, not to be visible to the user.
+ ///
+ internal Debugger.Value PermanentReference { get; set; }
+
+ private List _edges = new List();
+ ///
+ /// Outgoing edges.
+ ///
+ public IEnumerable Edges
+ {
+ get { return _edges; }
+ }
+
+ ///
+ /// Adds outgoing edge.
+ ///
+ internal void AddNamedEdge(ObjectNode targetNode, string edgeName)
+ {
+ _edges.Add(new ObjectEdge { Name = edgeName, SourceNode = this, TargetNode = targetNode });
+ }
+
+ private ObjectPropertyCollection _properties = new ObjectPropertyCollection();
+ ///
+ /// Properties representing atomic string values as part of the node.
+ ///
+ public ObjectPropertyCollection Properties
+ {
+ get { return _properties; }
+ }
+
+ ///
+ /// Adds string property.
+ ///
+ internal void AddProperty(string name, string value)
+ {
+ _properties.Add(new ObjectProperty { Name = name, Value = value });
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectProperty.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectProperty.cs
new file mode 100644
index 0000000000..233bd263af
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectProperty.cs
@@ -0,0 +1,27 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Primitive property (int, string, etc.) of an object, in string form.
+ ///
+ public class ObjectProperty
+ {
+ ///
+ /// e.g. "Age"
+ ///
+ public string Name { get; set; }
+ ///
+ /// e.g. "19"
+ ///
+ public string Value { get; set; }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectPropertyCollection.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectPropertyCollection.cs
new file mode 100644
index 0000000000..5113193ebf
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectPropertyCollection.cs
@@ -0,0 +1,19 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Collection of object primitive properties.
+ ///
+ public class ObjectPropertyCollection : List
+ {
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraphVisualizerViewContent.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraphVisualizerViewContent.cs
new file mode 100644
index 0000000000..6a805f10e7
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraphVisualizerViewContent.cs
@@ -0,0 +1,39 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Text;
+using System.Windows.Forms;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Gui;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// ViewContent of the visualizer.
+ ///
+ public class ObjectGraphVisualizerViewContent : AbstractViewContent
+ {
+ VisualizerWinFormsControl control = new VisualizerWinFormsControl();
+
+ ///
+ /// The representing the view.
+ ///
+ public override object Control
+ {
+ get
+ {
+ return control;
+ }
+ }
+
+ public ObjectGraphVisualizerViewContent()
+ {
+ this.TitleName = "Object graph visualizer";
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ShowObjectGraphVisualizerCommand.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ShowObjectGraphVisualizerCommand.cs
new file mode 100644
index 0000000000..81394c3116
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ShowObjectGraphVisualizerCommand.cs
@@ -0,0 +1,31 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Text;
+using System.Windows.Forms;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Gui;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Command in the tools menu for showing the object graph visualizer.
+ ///
+ public class ShowObjectGraphVisualizerCommand : AbstractMenuCommand
+ {
+ public override void Run()
+ {
+ VisualizerWPFWindow window = new VisualizerWPFWindow();
+ window.Topmost = true;
+ // fix non-editable TextBox bug
+ //System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(window);
+ window.Show();
+ //WorkbenchSingleton.Workbench.ShowView(new DebuggerVisualizerViewContent());
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/Lookup.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/Lookup.cs
new file mode 100644
index 0000000000..eff669edc9
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/Lookup.cs
@@ -0,0 +1,48 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+
+namespace Debugger.AddIn.Visualizers.Graph.Utils
+{
+ ///
+ /// Same like Dictionary, but can store multiple values for one key.
+ ///
+ public class Lookup
+ {
+ private Dictionary> _dictionary;
+
+ public Lookup()
+ {
+ _dictionary = new Dictionary>();
+ }
+
+ public LookupValueCollection this[TKey key]
+ {
+ get
+ {
+ LookupValueCollection values = null;
+ if (_dictionary.TryGetValue(key, out values))
+ {
+ return values;
+ }
+ return null;
+ }
+ }
+
+ public void Add(TKey key, TValue value)
+ {
+ LookupValueCollection values = null;;
+ if (!_dictionary.TryGetValue(key, out values))
+ {
+ values = new LookupValueCollection();
+ _dictionary.Add(key, values);
+ }
+ values.Add(value);
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/LookupValueCollection.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/LookupValueCollection.cs
new file mode 100644
index 0000000000..4f63814918
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/LookupValueCollection.cs
@@ -0,0 +1,18 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+
+namespace Debugger.AddIn.Visualizers.Graph.Utils
+{
+ ///
+ /// A collection of values for one key in the Lookup class.
+ ///
+ public class LookupValueCollection : List
+ {
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml
new file mode 100644
index 0000000000..8446aed80f
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml
@@ -0,0 +1,12 @@
+
+
+
+ Expression:
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml.cs
new file mode 100644
index 0000000000..f6b8aa7273
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml.cs
@@ -0,0 +1,33 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Interaction logic for VisualizerWPFControl.xaml
+ ///
+ public partial class VisualizerWPFControl : UserControl
+ {
+ public VisualizerWPFControl()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml
new file mode 100644
index 0000000000..def412b38d
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+ Expression:
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs
new file mode 100644
index 0000000000..182f4185f2
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs
@@ -0,0 +1,97 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+using ICSharpCode.SharpDevelop.Debugging;
+using ICSharpCode.SharpDevelop.Services;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Interaction logic for VisualizerWPFWindow.xaml
+ ///
+ public partial class VisualizerWPFWindow : Window
+ {
+ WindowsDebugger _debuggerService = null;
+
+ public VisualizerWPFWindow()
+ {
+ InitializeComponent();
+
+ _debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger;
+ if (_debuggerService == null)
+ throw new ApplicationException("Only windows debugger is currently supported");
+
+ _debuggerService.IsProcessRunningChanged += new EventHandler(debuggerService_IsProcessRunningChanged);
+ _debuggerService.DebugStopped += new EventHandler(_debuggerService_DebugStopped);
+ }
+
+ public void debuggerService_IsProcessRunningChanged(object sender, EventArgs e)
+ {
+ // on step or breakpoint hit
+ if (!_debuggerService.IsProcessRunning)
+ {
+ refreshGraph();
+ }
+ }
+
+ public void _debuggerService_DebugStopped(object sender, EventArgs e)
+ {
+ _debuggerService.IsProcessRunningChanged -= new EventHandler(debuggerService_IsProcessRunningChanged);
+ this.Close();
+ }
+
+ private void Inspect_Button_Click(object sender, RoutedEventArgs e)
+ {
+ refreshGraph();
+ }
+
+ void refreshGraph()
+ {
+ ObjectGraphBuilder graphBuilder = new ObjectGraphBuilder(_debuggerService);
+ ObjectGraph graph = null;
+
+ try
+ {
+ graph = graphBuilder.BuildGraphForExpression(txtExpression.Text);
+ }
+ catch(DebuggerVisualizerException ex)
+ {
+ guiHandleException(ex);
+ return;
+ }
+ catch(Debugger.GetValueException ex)
+ {
+ guiHandleException(ex);
+ return;
+ }
+
+ Layout.TreeLayouter layouter = new Layout.TreeLayouter();
+ Layout.PositionedGraph posGraph = layouter.CalculateLayout(graph, Layout.LayoutDirection.LeftRight);
+
+ GraphDrawer.Draw(posGraph, canvas);
+
+ //GraphDrawer drawer = new GraphDrawer(graph);
+ //drawer.Draw(canvas);
+ }
+
+ void guiHandleException(System.Exception ex)
+ {
+ MessageBox.Show(ex.Message, "Exception", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.Designer.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.Designer.cs
new file mode 100644
index 0000000000..929ca9b041
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.Designer.cs
@@ -0,0 +1,92 @@
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ partial class VisualizerWinFormsControl
+ {
+ ///
+ /// Designer variable used to keep track of non-visual components.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Disposes resources used by the control.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (components != null) {
+ components.Dispose();
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.txtExpression = new System.Windows.Forms.TextBox();
+ this.btnInspect = new System.Windows.Forms.Button();
+ this.lblInfo = new System.Windows.Forms.Label();
+ this.lblExpression = new System.Windows.Forms.Label();
+ this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+ this.SuspendLayout();
+ //
+ // txtExpression
+ //
+ this.txtExpression.Location = new System.Drawing.Point(88, 13);
+ this.txtExpression.Name = "txtExpression";
+ this.txtExpression.Size = new System.Drawing.Size(131, 20);
+ this.txtExpression.TabIndex = 0;
+ this.toolTip1.SetToolTip(this.txtExpression, "Expression (e.g. variable name) to be inspected");
+ //
+ // btnInspect
+ //
+ this.btnInspect.Location = new System.Drawing.Point(225, 10);
+ this.btnInspect.Name = "btnInspect";
+ this.btnInspect.Size = new System.Drawing.Size(75, 23);
+ this.btnInspect.TabIndex = 1;
+ this.btnInspect.Text = "Inspect";
+ this.btnInspect.UseVisualStyleBackColor = true;
+ this.btnInspect.Click += new System.EventHandler(this.BtnInspectClick);
+ //
+ // lblInfo
+ //
+ this.lblInfo.Location = new System.Drawing.Point(11, 58);
+ this.lblInfo.Name = "lblInfo";
+ this.lblInfo.Size = new System.Drawing.Size(349, 23);
+ this.lblInfo.TabIndex = 2;
+ this.lblInfo.Text = "< Result >";
+ //
+ // lblExpression
+ //
+ this.lblExpression.Location = new System.Drawing.Point(11, 14);
+ this.lblExpression.Name = "lblExpression";
+ this.lblExpression.Size = new System.Drawing.Size(71, 23);
+ this.lblExpression.TabIndex = 4;
+ this.lblExpression.Text = "Expression:";
+ //
+ // VisualizerWinFormsControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.lblExpression);
+ this.Controls.Add(this.lblInfo);
+ this.Controls.Add(this.btnInspect);
+ this.Controls.Add(this.txtExpression);
+ this.Name = "VisualizerWinFormsControl";
+ this.Size = new System.Drawing.Size(525, 426);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+ }
+ private System.Windows.Forms.Button btnInspect;
+ private System.Windows.Forms.ToolTip toolTip1;
+ private System.Windows.Forms.Label lblExpression;
+ private System.Windows.Forms.Label lblInfo;
+ private System.Windows.Forms.TextBox txtExpression;
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.cs
new file mode 100644
index 0000000000..87537b95d3
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.cs
@@ -0,0 +1,84 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+using System.Linq;
+
+using ICSharpCode.SharpDevelop.Debugging;
+using ICSharpCode.SharpDevelop.Services;
+
+namespace Debugger.AddIn.Visualizers.Graph
+{
+ ///
+ /// Windows forms control making up the object graph visualizer user interface/
+ ///
+ public partial class VisualizerWinFormsControl : UserControl
+ {
+ WindowsDebugger _debuggerService = null;
+
+ public VisualizerWinFormsControl()
+ {
+ //
+ // The InitializeComponent() call is required for Windows Forms designer support.
+ //
+ InitializeComponent();
+
+ _debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger;
+ if (_debuggerService == null)
+ throw new ApplicationException("Only windows debugger is currently supported");
+
+ _debuggerService.IsProcessRunningChanged += new EventHandler(debuggerService_IsProcessRunningChanged);
+ }
+
+ public void debuggerService_IsProcessRunningChanged(object sender, EventArgs e)
+ {
+ // on step, breakpoint hit
+ if (!_debuggerService.IsProcessRunning)
+ {
+ refreshGraph();
+ }
+ }
+
+ void BtnInspectClick(object sender, EventArgs e)
+ {
+ refreshGraph();
+ }
+
+ void refreshGraph()
+ {
+ ObjectGraphBuilder graphBuilder = new ObjectGraphBuilder(_debuggerService);
+ ObjectGraph graph = null;
+
+ try
+ {
+ graph = graphBuilder.BuildGraphForExpression(txtExpression.Text);
+ }
+ catch(DebuggerVisualizerException ex)
+ {
+ guiHandleException(ex);
+ return;
+ }
+ catch(Debugger.GetValueException ex)
+ {
+ guiHandleException(ex);
+
+ return;
+ }
+
+ // just a simple message for checking the graph is build ok, will be replaced by graph drawing of course
+ lblInfo.Text = string.Format("Done. Number of graph nodes: {0}, number of edges: {1}", graph.Nodes.Count(), graph.Edges.Count());
+ }
+
+ void guiHandleException(System.Exception ex)
+ {
+ lblInfo.Text = "< Result >";
+ MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/WinFormsControl.resx b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/WinFormsControl.resx
new file mode 100644
index 0000000000..7080a7d118
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/WinFormsControl.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file