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 97ffd5bbae..7d8f2fe478 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 @@ -44,7 +44,7 @@ namespace Debugger.AddIn.Visualizers.Graph return; } - double seconds = 1; + double seconds = 0.5; var durationMove = new Duration(TimeSpan.FromSeconds(seconds)); var durationFade = durationMove; 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 0caf226d5f..20160454e6 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 @@ -68,19 +68,22 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout treeNodeFor[objectGraphNode] = newTreeNode; double subtreeSize = 0; - foreach (ObjectEdge edge in objectGraphNode.Edges) + foreach (ObjectProperty property in objectGraphNode.ComplexProperties) { - ObjectNode neighbor = edge.TargetNode; - if (seenNodes.ContainsKey(neighbor)) + if (property.TargetNode != null) { - 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; + ObjectNode neighbor = property.TargetNode; + if (seenNodes.ContainsKey(neighbor)) + { + newTreeNode.AdditionalNeighbors.Add(new TreeEdge { Name = property.Name, SourceNode = newTreeNode, TargetNode = treeNodeFor[neighbor]}); + } + else + { + TreeNode newChild = buildTreeRecursive(neighbor); + newTreeNode.ChildEdges.Add(new TreeEdge { Name = property.Name, SourceNode = newTreeNode, TargetNode = newChild}); + + subtreeSize += newChild.SubtreeSize; + } } } subtreeSize = Math.Max(newTreeNode.LateralSizeWithMargin, subtreeSize); 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 index 2c23e7a38e..2363b0f37f 100644 --- 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 @@ -13,7 +13,7 @@ namespace Debugger.AddIn.Visualizers.Graph /// /// Named edge in the . /// - public class ObjectEdge : NamedEdge + /*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 index 2a500f853d..aa6a586504 100644 --- 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 @@ -41,7 +41,7 @@ namespace Debugger.AddIn.Visualizers.Graph /// /// All edges in the graph. /// - public IEnumerable Edges + /*public IEnumerable Edges { get { @@ -53,6 +53,6 @@ namespace Debugger.AddIn.Visualizers.Graph } } } - } + }*/ } } 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 9b91f6f303..d41f1bf718 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 @@ -107,13 +107,20 @@ namespace Debugger.AddIn.Visualizers.Graph { ObjectNode thisNode = createNewNode(rootValue); + // David: by calling this, we get an array of values, most of them probably invalid, + // it would be nice to be able to get a collection of 'values' + // that are valid (basically a snapshot of object's state) + // - a collection of custom objects, + // that contain the string value and DebugType, + // and can enumerate child values. + // It would be also nice to return IEnumerable or ReadonlyCollection + // http://blogs.msdn.com/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx /*string[] memberValues = rootValue.GetMemberValuesAsString(_bindingFlags); foreach (string memberValue in memberValues) { //Value memberValuePerm = memberValue.GetPermanentReference(); }*/ - foreach(Expression memberExpr in rootValue.Expression.AppendObjectMembers(rootValue.Type, _bindingFlags)) { @@ -123,27 +130,30 @@ namespace Debugger.AddIn.Visualizers.Graph 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); + string memberValueAsString = memberExpr.Evaluate(debuggerService.DebuggedProcess).AsString; + thisNode.AddAtomicProperty(memberName, memberValueAsString, memberExpr); } else { + ObjectNode targetNode = null; 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); + 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); } + else + { + targetNode = null; + } + thisNode.AddComplexProperty(memberName, "", memberExpr, targetNode); } } @@ -203,7 +213,7 @@ namespace Debugger.AddIn.Visualizers.Graph /// Hash code of the object in the debugee. private int invokeGetHashCode(Value value) { - // Dadid: I had hard time finding out how to invoke static method + // David: I had hard time finding out how to invoke static method // value.InvokeMethod is nice for instance methods. // what about MethodInfo.Invoke() ? // also, there could be an overload that takes 1 parameter instead of array 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 index 35e451fa96..b546c53fcf 100644 --- 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 @@ -7,21 +7,22 @@ using System; using System.Collections.Generic; using System.Text; +using Debugger.Expressions; namespace Debugger.AddIn.Visualizers.Graph { /// /// Node in the . /// - public class ObjectNode - { - /// + public class ObjectNode + { + /// /// Additional info useful for internal algorithms, not to be visible to the user. /// - internal Debugger.Value PermanentReference { get; set; } - internal int HashCode { get; set; } - - private List _edges = new List(); + internal Debugger.Value PermanentReference { get; set; } + internal int HashCode { get; set; } + + /*private List _edges = new List(); /// /// Outgoing edges. /// @@ -36,23 +37,67 @@ namespace Debugger.AddIn.Visualizers.Graph internal void AddNamedEdge(ObjectNode targetNode, string edgeName) { _edges.Add(new ObjectEdge { Name = edgeName, SourceNode = this, TargetNode = targetNode }); - } + }*/ + + class PropertyComparer : IComparer + { + public int Compare(ObjectProperty prop1, ObjectProperty prop2) + { + return prop1.Name.CompareTo(prop2.Name); + } + } + + private static PropertyComparer propertySortComparer = new PropertyComparer(); + + private bool sorted = false; - private List _properties = new List(); - /// - /// Properties representing atomic string values as part of the node. - /// - public List Properties - { - get { return _properties; } - } + private List _properties = new List(); + /// + /// Properties (either atomic or complex) of the object this node represents. + /// + public List Properties + { + get + { + if (!sorted) + { + _properties.Sort(propertySortComparer); + sorted = true; + } + return _properties; + } + } + /// + /// Only complex properties filtered out of + /// + public IEnumerable ComplexProperties + { + get + { + foreach (var property in Properties) + { + if (!property.IsAtomic) + yield return property; + } + } + } - /// - /// Adds string property. - /// - internal void AddProperty(string name, string value) - { - _properties.Add(new ObjectProperty { Name = name, Value = value }); - } - } + /// + /// Adds primitive property. + /// + internal void AddAtomicProperty(string name, string value, Expression expression) + { + _properties.Add(new ObjectProperty + { Name = name, Value = value, Expression = expression, IsAtomic = true, TargetNode = null }); + } + + /// + /// Adds complex property. + /// + internal void AddComplexProperty(string name, string value, Expression expression, ObjectNode targetNode) + { + _properties.Add(new ObjectProperty + { Name = name, Value = value, Expression = expression, IsAtomic = false, TargetNode = targetNode }); + } + } } 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 index 233bd263af..8f647d7fb7 100644 --- 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 @@ -11,7 +11,7 @@ using System.Text; namespace Debugger.AddIn.Visualizers.Graph { /// - /// Primitive property (int, string, etc.) of an object, in string form. + /// Primitive property of an object, in string form. /// public class ObjectProperty { @@ -23,5 +23,17 @@ namespace Debugger.AddIn.Visualizers.Graph /// e.g. "19" /// public string Value { get; set; } + /// + /// Expression used for obtaining this property + /// + public Debugger.Expressions.Expression Expression { get; set; } + /// + /// Node that this property points to. Can be null. Always null if is true. + /// + public ObjectNode TargetNode { get; set; } + /// + /// Is this property of atomic type? (int, string, etc.) + /// + public bool IsAtomic { get; set; } } } 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 index 87537b95d3..09621ecf01 100644 --- 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 @@ -72,7 +72,7 @@ namespace Debugger.AddIn.Visualizers.Graph } // 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()); + //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)