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 a7ab64f5bb..369d9f51d1 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
@@ -168,8 +168,11 @@
+
+
+
@@ -192,6 +195,8 @@
+
+
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/CanvasLocationAdapter.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/CanvasLocationAdapter.cs
new file mode 100644
index 0000000000..4549f46345
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/CanvasLocationAdapter.cs
@@ -0,0 +1,35 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Debugger.AddIn.Visualizers.Graph.Drawing
+{
+ ///
+ /// Provides LocationProperty, which enables animating Canvas.LeftProperty and Canvas.TopProperty
+ /// at the same time using PointAnimation.
+ ///
+ public class CanvasLocationAdapter : UIElement
+ {
+ ///
+ /// Add this dependency property to UIElement object and animate it using PointAnimation.
+ ///
+ public static DependencyProperty LocationProperty = DependencyProperty.RegisterAttached("Location", typeof(Point), typeof(Canvas), new FrameworkPropertyMetadata(new Point(0, 0), new PropertyChangedCallback(locationChanged)), new ValidateValueCallback(IsPointValid));
+
+ private static void locationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ Canvas.SetLeft((UIElement)d, ((Point)e.NewValue).X);
+ Canvas.SetTop((UIElement)d, ((Point)e.NewValue).Y);
+ }
+
+ private static bool IsPointValid(object o)
+ {
+ return true;
+ }
+ }
+}
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
index 4f583503d0..97ffd5bbae 100644
--- 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
@@ -12,6 +12,7 @@ using System.Windows.Controls;
using System.Windows.Media;
using System.Windows;
using System.Windows.Shapes;
+using System.Windows.Media.Animation;
using Debugger.AddIn.Visualizers.Graph.Drawing;
using Debugger.AddIn.Visualizers.Graph.Layout;
@@ -20,98 +21,179 @@ namespace Debugger.AddIn.Visualizers.Graph
///
/// Draws on Canvas.
///
- public class GraphDrawer
- {
- public GraphDrawer()
- {
- }
-
- ///
- /// Draws on Canvas.
- ///
- /// Graph to draw.
- /// Destination Canvas.
- public static void Draw(PositionedGraph posGraph, Canvas canvas)
- {
- canvas.Children.Clear();
-
- // draw nodes
- foreach (PositionedNode node in posGraph.Nodes)
- {
- canvas.Children.Add(node.NodeVisualControl);
- Canvas.SetLeft(node.NodeVisualControl, node.Left);
- Canvas.SetTop(node.NodeVisualControl, node.Top);
- }
-
- // draw edges
- foreach (PositionedEdge edge in posGraph.Edges)
- {
- Path edgePath = createEdgeWithArrow(edge);
- canvas.Children.Add(edgePath);
- }
- }
-
- private static Path createEdgeWithArrow(PositionedEdge edge)
- {
- Path path = new Path();
- path.Stroke = Brushes.Black;
- path.Fill = Brushes.Black;
- path.StrokeThickness = 1;
+ public class GraphDrawer
+ {
+ Canvas canvas;
+
+ public GraphDrawer(Canvas canvas)
+ {
+ this.canvas = canvas;
+ }
+
+ ///
+ /// Starts animation from oldGraph to newGraph.
+ ///
+ ///
+ ///
+ ///
+ public void StartAnimation(PositionedGraph oldGraph, PositionedGraph newGraph, GraphDiff diff)
+ {
+ if (oldGraph == null)
+ {
+ Draw(newGraph);
+ return;
+ }
+
+ double seconds = 1;
+ var durationMove = new Duration(TimeSpan.FromSeconds(seconds));
+ var durationFade = durationMove;
+
+ DoubleAnimation fadeOutAnim = new DoubleAnimation(1.0, 0.0, durationFade);
+ DoubleAnimation fadeInAnim = new DoubleAnimation(0.0, 1.0, durationFade);
+
+ foreach (UIElement drawing in canvas.Children)
+ {
+ var arrow = drawing as Path;
+ if (arrow != null)
+ {
+ arrow.BeginAnimation(UIElement.OpacityProperty, fadeOutAnim);
+ }
+ }
+
+ foreach (PositionedEdge edge in newGraph.Edges)
+ {
+ addEdgeToCanvas(edge).BeginAnimation(UIElement.OpacityProperty, fadeInAnim);
+ }
+
+ foreach (PositionedNode removedNode in diff.RemovedNodes)
+ {
+ removedNode.NodeVisualControl.BeginAnimation(UIElement.OpacityProperty, fadeOutAnim);
+ }
+
+ foreach (PositionedNode addedNode in diff.AddedNodes)
+ {
+ addNodeToCanvas(addedNode).BeginAnimation(UIElement.OpacityProperty, fadeInAnim);
+ }
+
+ bool first = true;
+ foreach (PositionedNode node in diff.ChangedNodes)
+ {
+ var newNode = diff.GetMatchingNewNode(node);
+
+ PointAnimation anim = new PointAnimation();
+ if (first)
+ {
+ anim.Completed += new EventHandler((o, e) => { Draw(newGraph); });
+ first = false;
+ }
+ //anim.From = new Point(Canvas.GetLeft(node.NodeVisualControl), Canvas.GetTop(node.NodeVisualControl));
+ anim.From = node.LeftTop;
+
+ anim.To = newNode.LeftTop;
+ anim.DecelerationRatio = 0.3;
+ anim.AccelerationRatio = 0.3;
+ anim.Duration = durationMove;
+ node.NodeVisualControl.BeginAnimation(CanvasLocationAdapter.LocationProperty, anim);
+ }
+ }
+
+ ///
+ /// Draws on Canvas.
+ ///
+ /// Graph to draw.
+ /// Destination Canvas.
+ public void Draw(PositionedGraph posGraph)
+ {
+ canvas.Children.Clear();
+
+ // draw nodes
+ foreach (PositionedNode node in posGraph.Nodes)
+ {
+ addNodeToCanvas(node);
+ }
+
+ // draw edges
+ foreach (PositionedEdge edge in posGraph.Edges)
+ {
+ addEdgeToCanvas(edge);
+ }
+ }
+
+ private NodeControl addNodeToCanvas(PositionedNode node)
+ {
+ canvas.Children.Add(node.NodeVisualControl);
+ Canvas.SetLeft(node.NodeVisualControl, node.Left);
+ Canvas.SetTop(node.NodeVisualControl, node.Top);
+ return node.NodeVisualControl;
+ }
+
+ private Path addEdgeToCanvas(PositionedEdge edge)
+ {
+ Path edgePath = createEdgeWithArrow(edge);
+ canvas.Children.Add(edgePath);
+ return edgePath;
+ }
+
+ private Path createEdgeWithArrow(PositionedEdge edge)
+ {
+ Path path = new Path();
+ path.Stroke = Brushes.Black;
+ path.Fill = Brushes.Black;
+ path.StrokeThickness = 1;
- PathGeometry geometry = new PathGeometry();
+ PathGeometry geometry = new PathGeometry();
- geometry.Figures.Add(createEdgeSpline(edge));
- geometry.Figures.Add(createEdgeArrow(edge));
-
- path.Data = geometry;
- return path;
- }
-
- private static PathFigure createEdgeSpline(PositionedEdge edge)
- {
- PathFigure figure = new PathFigure();
- figure.IsClosed = false;
- figure.IsFilled = false;
-
- figure.StartPoint = edge.SplinePoints[0];
- for (int i = 1; i < edge.SplinePoints.Count; i += 3)
- {
- figure.Segments.Add(new BezierSegment(edge.SplinePoints[i], edge.SplinePoints[i + 1], edge.SplinePoints[i + 2], true));
- }
-
- return figure;
- }
-
- private static PathFigure createEdgeArrow(PositionedEdge edge)
- {
+ geometry.Figures.Add(createEdgeSpline(edge));
+ geometry.Figures.Add(createEdgeArrow(edge));
+
+ path.Data = geometry;
+ return path;
+ }
+
+ private PathFigure createEdgeSpline(PositionedEdge edge)
+ {
+ PathFigure figure = new PathFigure();
+ figure.IsClosed = false;
+ figure.IsFilled = false;
+
+ figure.StartPoint = edge.SplinePoints[0];
+ for (int i = 1; i < edge.SplinePoints.Count; i += 3)
+ {
+ figure.Segments.Add(new BezierSegment(edge.SplinePoints[i], edge.SplinePoints[i + 1], edge.SplinePoints[i + 2], true));
+ }
+
+ return figure;
+ }
+
+ private PathFigure createEdgeArrow(PositionedEdge edge)
+ {
+ Point splineEndPoint = edge.SplinePoints[edge.SplinePoints.Count - 1];
+ Point splineEndHandlePoint = edge.SplinePoints[edge.SplinePoints.Count - 2];
+
+ Vector tangent = splineEndPoint - splineEndHandlePoint;
+ tangent.Normalize();
+ tangent = tangent * 20;
+ Point basePoint = splineEndPoint - 0.2 * tangent;
+
PathFigure arrowFigure = new PathFigure();
- arrowFigure.IsClosed = true;
- arrowFigure.IsFilled = true;
-
- Point endPoint = edge.SplinePoints[edge.SplinePoints.Count - 1];
- Point endHandlePoint = edge.SplinePoints[edge.SplinePoints.Count - 2];
-
- Vector tangent = endPoint - endHandlePoint;
- tangent.Normalize();
- tangent = tangent * 20;
- Point basePoint = endPoint - 0.2 * tangent;
+ arrowFigure.IsClosed = true;
+ arrowFigure.IsFilled = true;
- arrowFigure.StartPoint = basePoint + tangent * 0.4; // arrow tip
-
- Vector tangent2 = rotate90(tangent);
- arrowFigure.Segments.Add(new LineSegment(basePoint + tangent2 * 0.15, true));
- arrowFigure.Segments.Add(new LineSegment(basePoint - tangent2 * 0.15, true));
-
+ arrowFigure.StartPoint = basePoint + tangent * 0.4; // arrow tip
+ Vector tangent2 = rotate90(tangent);
+ arrowFigure.Segments.Add(new LineSegment(basePoint + tangent2 * 0.15, true));
+ arrowFigure.Segments.Add(new LineSegment(basePoint - tangent2 * 0.15, true));
+
return arrowFigure;
- }
-
- private static Vector rotate90(Vector v)
- {
- // (x, y) -> (y, -x)
- double t = v.X;
- v.X = v.Y;
- v.Y = -t;
- return v;
- }
- }
+ }
+
+ private static Vector rotate90(Vector v)
+ {
+ // (x, y) -> (y, -x)
+ double t = v.X;
+ v.X = v.Y;
+ v.Y = -t;
+ return v;
+ }
+ }
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/GraphDiff.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/GraphDiff.cs
new file mode 100644
index 0000000000..0b4952f7b7
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/GraphDiff.cs
@@ -0,0 +1,82 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Debugger.AddIn.Visualizers.Graph.Utils;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Describes changes between 2 s.
+ ///
+ public class GraphDiff
+ {
+ private List addedNodes = new List();
+ private List deletedNodes = new List();
+ private List changedNodes = new List();
+ private Dictionary matching = new Dictionary();
+
+ ///
+ /// Nodes in the new graph that were added.
+ ///
+ public IList AddedNodes
+ {
+ get { return addedNodes.AsReadOnly(); }
+ }
+
+ ///
+ /// Nodes in the old graph that were removed.
+ ///
+ public IList RemovedNodes
+ {
+ get { return deletedNodes.AsReadOnly(); }
+ }
+
+ ///
+ /// Nodes in the old graph that were chaged.
+ /// These have matching new nodes, which can be obtained by .
+ ///
+ public IList ChangedNodes
+ {
+ get { return changedNodes.AsReadOnly(); }
+ }
+
+ public PositionedNode GetMatchingNewNode(PositionedNode oldNode)
+ {
+ return matching.GetValue(oldNode);
+ }
+
+ internal void SetAdded(PositionedNode addedNode)
+ {
+ addedNodes.Add(addedNode);
+ }
+
+ internal void SetRemoved(PositionedNode removeddNode)
+ {
+ deletedNodes.Add(removeddNode);
+ }
+
+ internal void SetMatching(PositionedNode matchFrom, PositionedNode matchTo)
+ {
+ matching[matchFrom] = matchTo;
+ changedNodes.Add(matchFrom);
+ }
+
+ public GraphDiff()
+ {
+
+ }
+
+ /*public void MakeReadOnly()
+ {
+ addedNodes = ((List)addedNodes).AsReadOnly();
+ deletedNodes = ((List)deletedNodes).AsReadOnly();
+ changedNodes = ((List)changedNodes).AsReadOnly();
+ }*/
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/GraphMatcher.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/GraphMatcher.cs
new file mode 100644
index 0000000000..e8a583c588
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/GraphMatcher.cs
@@ -0,0 +1,100 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using Debugger.AddIn.Visualizers.Graph.Utils;
+
+namespace Debugger.AddIn.Visualizers.Graph.Layout
+{
+ ///
+ /// Calculates diff of 2 s.
+ ///
+ public class GraphMatcher
+ {
+ public GraphMatcher()
+ {
+ }
+
+ public GraphDiff MatchGraphs(PositionedGraph oldGraph, PositionedGraph newGraph)
+ {
+ // handle any of the graphs null
+ if (oldGraph == null)
+ {
+ if (newGraph == null)
+ {
+ return new GraphDiff();
+ }
+ else
+ {
+ GraphDiff addAllDiff = new GraphDiff();
+ foreach (PositionedNode newNode in newGraph.Nodes)
+ {
+ addAllDiff.SetAdded(newNode);
+ }
+ return addAllDiff;
+ }
+ }
+
+ // both graph are not null
+ GraphDiff diff = new GraphDiff();
+
+ Dictionary newNodeForHashCode = buildHashToNodeMap(newGraph);
+ Dictionary newNodeMatched = new Dictionary();
+
+ foreach (PositionedNode oldNode in oldGraph.Nodes)
+ {
+ PositionedNode matchingNode = matchNode(oldNode, newNodeForHashCode);
+ if (matchingNode != null)
+ {
+ diff.SetMatching(oldNode, matchingNode);
+ newNodeMatched[matchingNode] = true;
+ }
+ else
+ {
+ diff.SetRemoved(oldNode);
+ }
+ }
+ foreach (PositionedNode newNode in newGraph.Nodes)
+ {
+ if (!newNodeMatched.ContainsKey(newNode))
+ {
+ diff.SetAdded(newNode);
+ }
+ }
+
+ return diff;
+ }
+
+ private Dictionary buildHashToNodeMap(PositionedGraph graph)
+ {
+ var hashToNodeMap = new Dictionary();
+ foreach (PositionedNode node in graph.Nodes)
+ {
+ hashToNodeMap[node.ObjectNode.HashCode] = node;
+ }
+ return hashToNodeMap;
+ }
+
+ private PositionedNode matchNode(PositionedNode oldNode, Dictionary newNodeMap)
+ {
+ PositionedNode newNodeFound = newNodeMap.GetValue(oldNode.ObjectNode.HashCode);
+ if ((newNodeFound != null) && isSameAddress(oldNode, newNodeFound))
+ {
+ return newNodeFound;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private bool isSameAddress(PositionedNode node1, PositionedNode node2)
+ {
+ return node1.ObjectNode.PermanentReference.GetObjectAddress() == node2.ObjectNode.PermanentReference.GetObjectAddress();
+ }
+ }
+}
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
index 54373693a8..85084708cb 100644
--- 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
@@ -12,13 +12,20 @@ using System.Windows;
namespace Debugger.AddIn.Visualizers.Graph.Layout
{
///
- /// Node with position information.
+ /// Node with added position information.
///
public class PositionedNode
{
- public PositionedNode(NodeControl nodeVisualControl)
+ private ObjectNode objectNode;
+ public ObjectNode ObjectNode
+ {
+ get { return objectNode; }
+ }
+
+ public PositionedNode(NodeControl nodeVisualControl, ObjectNode objectNode)
{
this.nodeVisualControl = nodeVisualControl;
+ this.objectNode = objectNode;
}
public double Left { get; set; }
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
index 77ad5044e4..36b01e9bf5 100644
--- 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
@@ -31,11 +31,6 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
{
}
- private TreeNode createTreeNode(NodeControl nodeVisualControl)
- {
- return TreeNode.Create(this.layoutDirection, nodeVisualControl);
- }
-
///
/// Calculates layout for given .
///
@@ -66,7 +61,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
nodeVisualControl.GraphNode = objectGraphNode;
nodeVisualControl.Measure(new Size(500, 500));
- TreeNode newTreeNode = createTreeNode(nodeVisualControl);
+ TreeNode newTreeNode = TreeNode.Create(this.layoutDirection, nodeVisualControl, objectGraphNode);
newTreeNode.HorizontalMargin = horizNodeMargin;
newTreeNode.VerticalMargin = vertNodeMargin;
resultGraph.nodes.Add(newTreeNode);
@@ -104,7 +99,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
{
// 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));
+ double center = node.ChildEdges.Count() == 0 ? 0 : 0.5 * (subtreeSize - (node.LateralSize + node.LateralMargin));
// design alternatives
// node.MainPos += center; // used this
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
index 4be7d73e92..4cb9271d64 100644
--- 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
@@ -18,11 +18,11 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
///
public abstract class TreeNode : PositionedNode
{
- public static TreeNode Create(LayoutDirection direction, NodeControl nodeVisualControl)
+ public static TreeNode Create(LayoutDirection direction, NodeControl nodeVisualControl, ObjectNode objectNode)
{
switch (direction) {
- case LayoutDirection.TopBottom: return new TreeNodeTB(nodeVisualControl);
- case LayoutDirection.LeftRight: return new TreeNodeLR(nodeVisualControl);
+ case LayoutDirection.TopBottom: return new TreeNodeTB(nodeVisualControl, objectNode);
+ case LayoutDirection.LeftRight: return new TreeNodeLR(nodeVisualControl, objectNode);
default: throw new DebuggerVisualizerException("Unsupported layout direction: " + direction.ToString());
}
}
@@ -30,7 +30,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
public double HorizontalMargin { get; set; }
public double VerticalMargin { get; set; }
- protected TreeNode(NodeControl nodeVisualControl) : base(nodeVisualControl)
+ protected TreeNode(NodeControl nodeVisualControl, ObjectNode objectNode) : base(nodeVisualControl, objectNode)
{
}
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
index 50efa075a1..0b668d5f44 100644
--- 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
@@ -10,11 +10,11 @@ using Debugger.AddIn.Visualizers.Graph.Drawing;
namespace Debugger.AddIn.Visualizers.Graph.Layout
{
///
- /// Description of TreeNodeLR.
+ /// TreeNode used in LR layout mode.
///
public class TreeNodeLR: TreeNode
{
- public TreeNodeLR(NodeControl nodeControl) : base(nodeControl)
+ public TreeNodeLR(NodeControl nodeControl, ObjectNode objectNode) : base(nodeControl, objectNode)
{
}
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
index 5c5a323ed3..ca68132f69 100644
--- 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
@@ -10,11 +10,11 @@ using Debugger.AddIn.Visualizers.Graph.Drawing;
namespace Debugger.AddIn.Visualizers.Graph.Layout
{
///
- /// Description of TreeNodeTB.
+ /// TreeNode used in TB layout mode.
///
public class TreeNodeTB : TreeNode
{
- public TreeNodeTB(NodeControl nodeControl) : base(nodeControl)
+ public TreeNodeTB(NodeControl nodeControl, ObjectNode objectNode) : base(nodeControl, objectNode)
{
}
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
index de649cd769..9b91f6f303 100644
--- 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
@@ -9,7 +9,6 @@ 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;
@@ -159,10 +158,11 @@ namespace Debugger.AddIn.Visualizers.Graph
private ObjectNode createNewNode(Value permanentReference)
{
ObjectNode newNode = new ObjectNode();
+ newNode.HashCode = invokeGetHashCode(permanentReference);
resultGraph.AddNode(newNode);
// remember this node's hashcode for quick lookup
- objectNodesForHashCode.Add(invokeGetHashCode(permanentReference), newNode);
+ objectNodesForHashCode.Add(newNode.HashCode, newNode);
// permanent reference to the object this node represents is useful for graph building,
// and matching nodes in animations
@@ -189,9 +189,9 @@ namespace Debugger.AddIn.Visualizers.Graph
{
// 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);
+ ulong objectAddress = value.GetObjectAddress();
ObjectNode nodeWithSameAddress = nodesWithSameHashCode.Find(
- node => { return objectAddress == getObjectValue(node.PermanentReference); } );
+ node => { return objectAddress == node.PermanentReference.GetObjectAddress(); } );
return nodeWithSameAddress;
}
}
@@ -239,7 +239,7 @@ namespace Debugger.AddIn.Visualizers.Graph
return (!typeOfValue.IsClass) || typeOfValue.IsString;
}
- #region helpers
+ #region Expression helpers
private Value getPermanentReference(Expression expr)
{
@@ -258,13 +258,7 @@ namespace Debugger.AddIn.Visualizers.Graph
private ulong getObjectAddress(Expression expr)
{
- return getObjectValue(expr.Evaluate(debuggerService.DebuggedProcess));
- }
-
- private ulong getObjectValue(Value val)
- {
- ICorDebugReferenceValue refVal = val.CorValue.CastTo();
- return refVal.Value;
+ return expr.Evaluate(debuggerService.DebuggedProcess).GetObjectAddress();
}
#endregion
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/DebuggerHelpers.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/DebuggerHelpers.cs
new file mode 100644
index 0000000000..49886eac20
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/DebuggerHelpers.cs
@@ -0,0 +1,23 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using Debugger.Wrappers.CorDebug;
+
+namespace Debugger.AddIn.Visualizers.Graph.Utils
+{
+ public static class DebuggerHelpers
+ {
+ ///
+ /// Gets underlying address of object in the debuggee.
+ ///
+ public static ulong GetObjectAddress(this Value val)
+ {
+ ICorDebugReferenceValue refVal = val.CorValue.CastTo();
+ return refVal.Value;
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/DictionaryExtensions.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/DictionaryExtensions.cs
new file mode 100644
index 0000000000..cc91a85fd5
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Utils/DictionaryExtensions.cs
@@ -0,0 +1,30 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+
+namespace Debugger.AddIn.Visualizers.Graph.Utils
+{
+ public static class DictionaryExtensions
+ {
+ ///
+ /// Gets value from Dictionary, returns null if not found.
+ ///
+ public static TValue GetValue(this Dictionary dictionary, TKey key) where TValue : class
+ {
+ TValue outValue;
+ if (dictionary.TryGetValue(key, out outValue))
+ {
+ return outValue;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+}
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
index 8d8743fe27..f17911cb25 100644
--- 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
@@ -28,30 +28,36 @@ namespace Debugger.AddIn.Visualizers.Graph
///
public partial class VisualizerWPFWindow : Window
{
- private WindowsDebugger _debuggerService;
+ private WindowsDebugger debuggerService;
private EnumViewModel layoutViewModel;
private ObjectGraph objectGraph;
+
+ private PositionedGraph oldGraph;
+ private PositionedGraph currentGraph;
+ private GraphDrawer graphDrawer;
public VisualizerWPFWindow()
{
InitializeComponent();
- _debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger;
- if (_debuggerService == null)
+ 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);
+ debuggerService.IsProcessRunningChanged += new EventHandler(debuggerService_IsProcessRunningChanged);
+ debuggerService.DebugStopped += new EventHandler(_debuggerService_DebugStopped);
this.layoutViewModel = new EnumViewModel();
this.layoutViewModel.PropertyChanged += new PropertyChangedEventHandler(layoutViewModel_PropertyChanged);
this.DataContext = this.layoutViewModel;
+
+ this.graphDrawer = new GraphDrawer(this.canvas);
}
public void debuggerService_IsProcessRunningChanged(object sender, EventArgs e)
{
// on step or breakpoint hit
- if (!_debuggerService.IsProcessRunning)
+ if (!debuggerService.IsProcessRunning)
{
refreshGraph();
}
@@ -59,7 +65,7 @@ namespace Debugger.AddIn.Visualizers.Graph
public void _debuggerService_DebugStopped(object sender, EventArgs e)
{
- _debuggerService.IsProcessRunningChanged -= new EventHandler(debuggerService_IsProcessRunningChanged);
+ debuggerService.IsProcessRunningChanged -= new EventHandler(debuggerService_IsProcessRunningChanged);
this.Close();
}
@@ -78,11 +84,12 @@ namespace Debugger.AddIn.Visualizers.Graph
void refreshGraph()
{
- ObjectGraphBuilder graphBuilder = new ObjectGraphBuilder(_debuggerService);
+ ObjectGraphBuilder graphBuilder = new ObjectGraphBuilder(debuggerService);
this.objectGraph = null;
try
{
+ ICSharpCode.Core.LoggingService.Debug("Debugger visualizer: Building graph for expression: " + txtExpression.Text);
this.objectGraph = graphBuilder.BuildGraphForExpression(txtExpression.Text);
}
catch(DebuggerVisualizerException ex)
@@ -104,10 +111,15 @@ namespace Debugger.AddIn.Visualizers.Graph
void layoutGraph(ObjectGraph graph)
{
+ ICSharpCode.Core.LoggingService.Debug("Debugger visualizer: Calculating graph layout");
Layout.TreeLayouter layouter = new Layout.TreeLayouter();
- Layout.PositionedGraph posGraph = layouter.CalculateLayout(graph, layoutViewModel.SelectedEnumValue);
+
+ this.oldGraph = this.currentGraph;
+ this.currentGraph = layouter.CalculateLayout(graph, layoutViewModel.SelectedEnumValue);
- GraphDrawer.Draw(posGraph, canvas);
+ var graphDiff = new GraphMatcher().MatchGraphs(oldGraph, currentGraph);
+ this.graphDrawer.StartAnimation(oldGraph, currentGraph, graphDiff);
+ //this.graphDrawer.Draw(currentGraph);
}
void guiHandleException(System.Exception ex)