Browse Source

- auto size Name column in node

- rewrote ObjectGraphBuilder so that now property Expressions are not evaluated until rendered

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4419 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Martin Koníček 17 years ago
parent
commit
dcee305a84
  1. 20
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml
  2. 68
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml.cs
  3. 20
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/ContentNode.cs
  4. 13
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/ContentPropertyNode.cs
  5. 4
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraphNode.cs
  6. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/NeatoEdgeRouter.cs
  7. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs
  8. 64
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs
  9. 12
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs
  10. 50
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs
  11. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/ObjectProperty.cs
  12. 12
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/AtomicType.cs
  13. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs

20
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml

@ -43,17 +43,19 @@
<GridView> <GridView>
<GridView.ColumnHeaderContainerStyle> <GridView.ColumnHeaderContainerStyle>
<Style> <Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/> <!--
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/> -->
<Setter Property="FrameworkElement.Height" Value="1"/>
</Style> </Style>
</GridView.ColumnHeaderContainerStyle> </GridView.ColumnHeaderContainerStyle>
<GridView.Columns> <GridView.Columns>
<!-- Expand button (either property or nested) --> <!-- Expand button (either property or nested) -->
<GridViewColumn Header="Plus" Width="35"> <GridViewColumn Header="Plus" Width="Auto">
<GridViewColumn.CellTemplate> <GridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<StackPanel> <StackPanel>
<ToggleButton x:Name="Expander" Width="20" Margin="0" IsChecked="{Binding IsExpanded}" Click="NestedExpandButton_Click" Padding="0">+</ToggleButton> <ToggleButton x:Name="Expander" Width="20" Margin="-4 -1 -4 -1" IsChecked="{Binding IsExpanded}" Click="NestedExpandButton_Click" Padding="0">+</ToggleButton>
<ToggleButton x:Name="PropertyExpander" Width="20" Margin="0" IsChecked="{Binding IsPropertyExpanded}" Click="PropertyExpandButton_Click" Padding="0">+</ToggleButton> <ToggleButton x:Name="PropertyExpander" Width="20" Margin="-4 -1 -4 -1" IsChecked="{Binding IsPropertyExpanded}" Click="PropertyExpandButton_Click" Padding="0">+</ToggleButton>
</StackPanel> </StackPanel>
<DataTemplate.Triggers> <DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=HasChildren}" Value="False"> <DataTrigger Binding="{Binding Path=HasChildren}" Value="False">
@ -70,24 +72,26 @@
</GridViewColumn.CellTemplate> </GridViewColumn.CellTemplate>
</GridViewColumn> </GridViewColumn>
<!-- Name --> <!-- Name -->
<GridViewColumn Header="Name" Width="60"> <GridViewColumn Header="Name" Width="Auto">
<GridViewColumn.CellTemplate> <GridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<!-- <!--
<TextBlock Text="hello" MinWidth="100"></TextBlock> <TextBlock Text="hello" MinWidth="100"></TextBlock>
--> -->
<TextBlock Text="{Binding Name}" MinWidth="80"></TextBlock> <StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"></TextBlock></StackPanel>
</DataTemplate> </DataTemplate>
</GridViewColumn.CellTemplate> </GridViewColumn.CellTemplate>
</GridViewColumn> </GridViewColumn>
<!-- Text --> <!-- Text -->
<GridViewColumn Header="Value" Width="80"> <GridViewColumn Header="Value " Width="Auto">
<GridViewColumn.CellTemplate> <GridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<!-- <!--
<TextBlock Text="val" MinWidth="100"></TextBlock> <TextBlock Text="val" MinWidth="100"></TextBlock>
--> -->
<TextBlock Text="{Binding Text}" MinWidth="80"></TextBlock> <StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Text}"></TextBlock></StackPanel>
</DataTemplate> </DataTemplate>
</GridViewColumn.CellTemplate> </GridViewColumn.CellTemplate>
</GridViewColumn> </GridViewColumn>

68
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml.cs

@ -4,7 +4,11 @@
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/> // <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@ -13,11 +17,10 @@ using System.Windows.Data;
using System.Windows.Documents; using System.Windows.Documents;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Debugger.AddIn.Visualizers.Graph.Layout;
using System;
using System.Collections.Generic;
using System.Linq;
using Debugger.AddIn.Visualizers.Common; using Debugger.AddIn.Visualizers.Common;
using Debugger.AddIn.Visualizers.Graph.Layout;
using System.Windows.Threading;
namespace Debugger.AddIn.Visualizers.Graph.Drawing namespace Debugger.AddIn.Visualizers.Graph.Drawing
{ {
@ -61,6 +64,53 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
this.view = getInitialView(this.root); this.view = getInitialView(this.root);
// data virtualization, PropertyNodeViewModel implements IEvaluate // data virtualization, PropertyNodeViewModel implements IEvaluate
this.listView.ItemsSource = new VirtualizingObservableCollection<ContentNode>(this.view); this.listView.ItemsSource = new VirtualizingObservableCollection<ContentNode>(this.view);
int maxLen = this.view.Max(contentNode => { return contentNode.Name.Length; } );
int spaces = Math.Max((int)(maxLen * 1.5), 0);
string sp = "";
for (int i = 0; i < spaces; i++)
sp += " ";
GridView gv = listView.View as GridView;
gv.Columns[1].Header = "Name" + sp;
//AutoSizeColumns();
/*DispatcherTimer t = new DispatcherTimer();
t.Interval = TimeSpan.FromMilliseconds(1000);
t.Start();
t.Tick += (s, ee) => { AutoSizeColumns(); t.Stop(); };*/
}
}
public void AutoSizeColumns()
{
//listView.UpdateLayout();
//listView.Measure(new Size(800, 800));
//double sum = 0;
GridView gv = listView.View as GridView;
if (gv != null)
{
foreach (var c in gv.Columns)
{
//var header = c.Header as GridViewColumnHeader;
// Code below was found in GridViewColumnHeader.OnGripperDoubleClicked() event handler (using Reflector)
// i.e. it is the same code that is executed when the gripper is double clicked
//var uw = c.GetType().GetMethod("UpdateActualWidth", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic);
//uw.Invoke(c, new object[] { });
//if (double.IsNaN(c.Width))
{
c.Width = c.ActualWidth;
}
c.Width = double.NaN;
/*var dw = c.GetType().GetProperty("DesiredWidth", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic);
double desired = (double)dw.GetValue(c, null);
c.Width = c.ActualWidth; // ActualWidth is not correct until GridViewRowPresenter gets measured
c.Width = double.NaN;
sum += c.Width;*/
}
} }
} }
@ -85,6 +135,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
PositionedNodeProperty property = clickedNode.Property; PositionedNodeProperty property = clickedNode.Property;
//property.IsPropertyExpanded = !property.IsPropertyExpanded; // done by databinding //property.IsPropertyExpanded = !property.IsPropertyExpanded; // done by databinding
clickedButton.Content = property.IsPropertyExpanded ? "-" : "+"; clickedButton.Content = property.IsPropertyExpanded ? "-" : "+";
if (property.IsPropertyExpanded) if (property.IsPropertyExpanded)
{ {
OnPropertyExpanded(property); OnPropertyExpanded(property);
@ -112,6 +163,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
this.view.Insert(clickedIndex + i, childNode); this.view.Insert(clickedIndex + i, childNode);
i++; i++;
} }
// insertChildren(clickedNode, this.view, clickedIndex); // TODO
OnContentNodeExpanded(clickedNode); OnContentNodeExpanded(clickedNode);
} }
else else
@ -124,19 +176,21 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
} }
OnContentNodeCollapsed(clickedNode); OnContentNodeCollapsed(clickedNode);
} }
//AutoSizeColumns();
// set to Auto again to resize columns // set to Auto again to resize columns
var colName = (this.listView.View as GridView).Columns[0]; /*var colName = (this.listView.View as GridView).Columns[0];
var colValue = (this.listView.View as GridView).Columns[1]; var colValue = (this.listView.View as GridView).Columns[1];
colName.Width = 300; colName.Width = 300;
colName.Width = double.NaN; colName.Width = double.NaN;
colValue.Width = 300; colValue.Width = 300;
colValue.Width = double.NaN; colValue.Width = double.NaN;
//this.view.Insert(0, new NestedNodeViewModel()); //this.view.Insert(0, new ContentNode());
//this.view.RemoveAt(0); //this.view.RemoveAt(0);
this.listView.UpdateLayout(); this.listView.UpdateLayout();
this.listView.Width = colName.ActualWidth + colValue.ActualWidth + 30; this.listView.Width = colName.ActualWidth + colValue.ActualWidth + 30;
this.listView.Width = double.NaN; this.listView.Width = double.NaN;*/
} }
private ObservableCollection<ContentNode> getInitialView(ContentNode root) private ObservableCollection<ContentNode> getInitialView(ContentNode root)

20
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/ContentNode.cs

@ -88,22 +88,12 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
/// <summary> /// <summary>
/// Show a button to expand property associated with this node? /// Show a button to expand property associated with this node?
/// </summary> /// </summary>
public bool ShowExpandPropertyButton public virtual bool ShowExpandPropertyButton
{ {
get get
{ {
var thisAsPropertyNode = this as ContentPropertyNode; // this is NestedNodeViewModel -> no property, don't show expand button
if (thisAsPropertyNode == null) return false;
{
// this is NestedNodeViewModel -> no property, don't show expand button
return false;
}
else
{
// this is PositionedNodeViewModel -> show expand button when appropriate
PositionedNodeProperty property = thisAsPropertyNode.Property;
return (!property.IsAtomic && !property.IsNull);
}
} }
} }
@ -150,7 +140,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
public virtual void InitFrom(AbstractNode source, Expanded expanded) public virtual void InitFrom(AbstractNode source, Expanded expanded)
{ {
this.Name = getNestedNodeName(source); this.Name = getContentNodeName(source);
this.Text = ""; // lazy evaluated later this.Text = ""; // lazy evaluated later
this.IsNested = true; this.IsNested = true;
this.path = this.Parent == null ? this.Name : this.Parent.Path + "." + this.Name; this.path = this.Parent == null ? this.Name : this.Parent.Path + "." + this.Name;
@ -173,7 +163,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
} }
} }
private string getNestedNodeName(AbstractNode source) private string getContentNodeName(AbstractNode source)
{ {
if (source is ThisNode) if (source is ThisNode)
{ {

13
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/ContentPropertyNode.cs

@ -15,7 +15,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
{ {
PositionedNodeProperty positionedProperty; PositionedNodeProperty positionedProperty;
public ContentPropertyNode(PositionedGraphNode containingNode, ContentNode parent) public ContentPropertyNode(PositionedGraphNode containingNode, ContentNode parent)
: base(containingNode, parent) : base(containingNode, parent)
{ {
} }
@ -45,6 +45,15 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
this.Text = this.positionedProperty.Value; this.Text = this.positionedProperty.Value;
} }
public override bool ShowExpandPropertyButton
{
get
{
// show expand button when appropriate
return (!this.positionedProperty.IsAtomic && !this.positionedProperty.IsNull);
}
}
public override void InitFrom(AbstractNode source, Expanded expanded) public override void InitFrom(AbstractNode source, Expanded expanded)
{ {
if (!(source is PropertyNode)) if (!(source is PropertyNode))
@ -57,7 +66,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
this.IsNested = false; this.IsNested = false;
this.IsExpanded = false; // always false, property content nodes are never expanded this.IsExpanded = false; // always false, property content nodes are never expanded
this.positionedProperty = new PositionedNodeProperty( this.positionedProperty = new PositionedNodeProperty(
sourcePropertyNode.Property, this.ContainingNode, sourcePropertyNode.Property, this.ContainingNode,
expanded.Expressions.IsExpanded(sourcePropertyNode.Property.Expression)); expanded.Expressions.IsExpanded(sourcePropertyNode.Property.Expression));
} }
} }

4
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraphNode.cs

@ -73,7 +73,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
private void initVisualControl() private void initVisualControl()
{ {
this.nodeVisualControl = new PositionedGraphNodeControl(); this.nodeVisualControl = new PositionedGraphNodeControl();
this.nodeVisualControl.MaxHeight = 200; this.nodeVisualControl.MaxHeight = 300;
// propagate events from nodeVisualControl // propagate events from nodeVisualControl
this.nodeVisualControl.PropertyExpanded += new EventHandler<PositionedPropertyEventArgs>(NodeVisualControl_PropertyExpanded); this.nodeVisualControl.PropertyExpanded += new EventHandler<PositionedPropertyEventArgs>(NodeVisualControl_PropertyExpanded);
@ -104,7 +104,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
public void Measure() public void Measure()
{ {
this.nodeVisualControl.Measure(new Size(500, 500)); this.nodeVisualControl.Measure(new Size(800, 800));
} }
public double Left { get; set; } public double Left { get; set; }

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/NeatoEdgeRouter.cs

@ -30,7 +30,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
/// <returns><see cref="PositionedGraph" /> with preserved node positions and calculated edge positions.</returns> /// <returns><see cref="PositionedGraph" /> with preserved node positions and calculated edge positions.</returns>
public PositionedGraph CalculateEdges(PositionedGraph graphWithNodesPositioned) public PositionedGraph CalculateEdges(PositionedGraph graphWithNodesPositioned)
{ {
DotFormatter dotFormatter = new BoxDotFormatter(graphWithNodesPositioned); DotFormatter dotFormatter = new RecordDotFormatter(graphWithNodesPositioned);
// start Neato.exe // start Neato.exe
NeatoProcess neatoProcess = NeatoProcess.Start(); NeatoProcess neatoProcess = NeatoProcess.Start();

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraph.cs

@ -55,7 +55,7 @@ namespace Debugger.AddIn.Visualizers.Graph
{ {
seenNodes.Add(root); seenNodes.Add(root);
foreach(var prop in root.ComplexProperties) foreach(var prop in root.Properties)
{ {
if (prop.TargetNode != null && !seenNodes.Contains(prop.TargetNode)) if (prop.TargetNode != null && !seenNodes.Contains(prop.TargetNode))
determineReachableNodes(prop.TargetNode, seenNodes); determineReachableNodes(prop.TargetNode, seenNodes);

64
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs

@ -112,7 +112,7 @@ namespace Debugger.AddIn.Visualizers.Graph
public ObjectGraphNode ObtainNodeForExpression(Expression expr, out bool createdNewNode) public ObjectGraphNode ObtainNodeForExpression(Expression expr, out bool createdNewNode)
{ {
return ObtainNodeForValue(expr.GetPermanentReference(), out createdNewNode); return ObtainNodeForValue(expr.EvalPermanentReference(), out createdNewNode);
} }
/// <summary> /// <summary>
@ -157,11 +157,12 @@ namespace Debugger.AddIn.Visualizers.Graph
} }
// non-public members // non-public members
if (type.HasMembers(nonPublicInstanceMemberFlags)) var nonPublicProperties = getProperties(value, type, this.nonPublicInstanceMemberFlags);
if (nonPublicProperties.Count > 0)
{ {
var nonPublicMembersNode = new NonPublicMembersNode(); var nonPublicMembersNode = new NonPublicMembersNode();
node.AddChild(nonPublicMembersNode); node.AddChild(nonPublicMembersNode);
foreach (var nonPublicProperty in getProperties(value, type, this.nonPublicInstanceMemberFlags)) foreach (var nonPublicProperty in nonPublicProperties)
{ {
nonPublicMembersNode.AddChild(new PropertyNode(nonPublicProperty)); nonPublicMembersNode.AddChild(new PropertyNode(nonPublicProperty));
} }
@ -183,7 +184,26 @@ namespace Debugger.AddIn.Visualizers.Graph
{ {
List<ObjectGraphProperty> propertyList = new List<ObjectGraphProperty>(); List<ObjectGraphProperty> propertyList = new List<ObjectGraphProperty>();
// take all properties for this value (type = value's real type) foreach (PropertyInfo memberProp in shownType.GetProperties(flags))
{
if (memberProp.Name.Contains("<"))
continue;
// TODO just temporary - ObjectGraphProperty needs an expression
// to use expanded / nonexpanded (and to evaluate?)
Expression propExpression = value.Expression.AppendMemberReference(memberProp);
// Value, IsAtomic are lazy evaluated
//var t = memberProp.DeclaringType;
propertyList.Add(new ObjectGraphProperty
{ Name = memberProp.Name,
Expression = propExpression, Value = "",
/*PropInfo = memberProp,*/ IsAtomic = true, TargetNode = null });
}
return propertyList.Sorted(ObjectPropertyComparer.Instance);
/*// take all properties for this value (type = value's real type)
foreach(Expression memberExpr in value.Expression.AppendObjectMembers(shownType, flags)) foreach(Expression memberExpr in value.Expression.AppendObjectMembers(shownType, flags))
{ {
// skip private backing fields // skip private backing fields
@ -201,13 +221,12 @@ namespace Debugger.AddIn.Visualizers.Graph
} }
else else
{ {
ObjectGraphNode targetNode = null;
bool memberIsNull = memberExpr.IsNull(); bool memberIsNull = memberExpr.IsNull();
propertyList.Add(createComplexProperty(memberName, memberExpr, targetNode, memberIsNull)); propertyList.Add(createComplexProperty(memberName, memberExpr, null, memberIsNull));
} }
} }
return propertyList.Sorted(ObjectPropertyComparer.Instance); return propertyList.Sorted(ObjectPropertyComparer.Instance);*/
} }
/// <summary> /// <summary>
@ -217,23 +236,34 @@ namespace Debugger.AddIn.Visualizers.Graph
/// <param name="expandedNodes"></param> /// <param name="expandedNodes"></param>
private void loadNeighborsRecursive(ObjectGraphNode thisNode, ExpandedExpressions expandedNodes) private void loadNeighborsRecursive(ObjectGraphNode thisNode, ExpandedExpressions expandedNodes)
{ {
foreach(ObjectGraphProperty complexProperty in thisNode.ComplexProperties) //foreach(ObjectGraphProperty complexProperty in thisNode.ComplexProperties)
foreach(ObjectGraphProperty complexProperty in thisNode.Properties)
{ {
ObjectGraphNode targetNode = null; ObjectGraphNode targetNode = null;
// we are only evaluating expanded nodes here // we are only evaluating expanded nodes here
// (we have to do this to know the "shape" of the graph) // (we have to do this to know the "shape" of the graph)
// property laziness makes sense, as we are not evaluating atomic and non-expanded properties out of user's view // property laziness makes sense, as we are not evaluating atomic and non-expanded properties out of user's view
if (!complexProperty.IsNull && expandedNodes.IsExpanded(complexProperty.Expression)) if (/*!complexProperty.IsNull && we dont know yet if it's null */expandedNodes.IsExpanded(complexProperty.Expression))
{ {
Value memberValue = complexProperty.Expression.GetPermanentReference(); // if expanded, evaluate this property
Value memberValue = complexProperty.Expression.Evaluate(this.debuggerService.DebuggedProcess);
bool createdNew; if (memberValue.IsNull)
// get existing node (loop) or create new {
targetNode = ObtainNodeForValue(memberValue, out createdNew); continue;
if (createdNew) }
else
{ {
// if member node is new, recursively build its subtree // if property value is not null, create neighbor
loadNeighborsRecursive(targetNode, expandedNodes); memberValue = memberValue.GetPermanentReference();
bool createdNew;
// get existing node (loop) or create new
targetNode = ObtainNodeForValue(memberValue, out createdNew);
if (createdNew)
{
// if member node is new, recursively build its subtree
loadNeighborsRecursive(targetNode, expandedNodes);
}
} }
} }
else else

12
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphNode.cs

@ -39,16 +39,24 @@ namespace Debugger.AddIn.Visualizers.Graph
get; set; get; set;
} }
public IEnumerable<ObjectGraphProperty> Properties
{
get
{
return this.Content.FlattenPropertyNodes().Select(node => {return node.Property; });
}
}
// TODO just for ObjectGraphBuilder, remove // TODO just for ObjectGraphBuilder, remove
/// <summary> /// <summary>
/// Only complex properties filtered out of <see cref="Properties"/> /// Only complex properties filtered out of <see cref="Properties"/>
/// </summary> /// </summary>
public IEnumerable<ObjectGraphProperty> ComplexProperties /*public IEnumerable<ObjectGraphProperty> ComplexProperties
{ {
get get
{ {
return this.Content.FlattenPropertyNodes().Select(node => {return node.Property; }); return this.Content.FlattenPropertyNodes().Select(node => {return node.Property; });
} }
} }*/
} }
} }

50
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs

@ -8,21 +8,37 @@ using ICSharpCode.SharpDevelop.Services;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using Debugger.AddIn.Visualizers.Utils;
namespace Debugger.AddIn.Visualizers.Graph namespace Debugger.AddIn.Visualizers.Graph
{ {
/// <summary> /// <summary>
/// ObjectProperty used in ObjectGraph. Has TargetNode. /// ObjectProperty used in ObjectGraph. Has TargetNode.
/// Support on-demand evaluation of Value property. /// Support on-demand evaluation of Value property.
/// </summary> /// </summary>
public class ObjectGraphProperty : ObjectProperty, IEvaluate public class ObjectGraphProperty : ObjectProperty, IEvaluate
{ {
/// <summary> /// <summary>
/// Node that this property points to. Can be null. Always null if <see cref="IsAtomic"/> is true. /// Node that this property points to. Can be null. Always null if <see cref="IsAtomic"/> is true.
/// </summary>
public ObjectGraphNode TargetNode { get; set; }
//private Expressions.Expression containingObjectExpression;
/*public ObjectGraphProperty(Expressions.Expression containingObjectExpression)
{
if (containingObjectExpression == null)
throw new ArgumentNullException("containingObjectExpression");
this.containingObjectExpression = containingObjectExpression;
}*/
/// <summary>
/// MemberInfo used for obtaining value of this property
/// </summary> /// </summary>
public ObjectGraphNode TargetNode { get; set; } public Debugger.MetaData.MemberInfo PropInfo { get; set; }
bool evaluateCalled = false;
bool evaluateCalled = false;
public bool IsEvaluated public bool IsEvaluated
{ {
get { return this.evaluateCalled; } get { return this.evaluateCalled; }
@ -30,13 +46,23 @@ namespace Debugger.AddIn.Visualizers.Graph
public void Evaluate() public void Evaluate()
{ {
/*if (this.PropInfo == null)
{
throw new DebuggerVisualizerException("Cannot evaluate property with missing MemberInfo");
}
Value debuggerVal = this.containingObjectExpression.Evaluate(WindowsDebugger.CurrentProcess).GetMemberValue(this.PropInfo);*/
if (this.Expression == null) if (this.Expression == null)
{ {
throw new DebuggerVisualizerException("Cannot evaluate property with missing Expression"); throw new DebuggerVisualizerException("Cannot evaluate property with missing Expression");
} }
Value debuggerVal = this.Expression.Evaluate(WindowsDebugger.CurrentProcess); Value debuggerVal = this.Expression.Evaluate(WindowsDebugger.CurrentProcess);
this.Value = debuggerVal.IsNull ? string.Empty : debuggerVal.InvokeToString();
this.IsAtomic = debuggerVal.Type.IsAtomic();
this.IsNull = debuggerVal.IsNull;
// null and complex properties evaluate to empty string
this.Value = debuggerVal.IsNull || (!this.IsAtomic) ? string.Empty : debuggerVal.InvokeToString();
this.evaluateCalled = true; this.evaluateCalled = true;
} }
} }
} }

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/ObjectProperty.cs

@ -24,7 +24,7 @@ namespace Debugger.AddIn.Visualizers
public string Value { get; set; } public string Value { get; set; }
/// <summary> /// <summary>
/// Expression used for obtaining this property /// Expression used for obtaining value of this property
/// </summary> /// </summary>
public Debugger.Expressions.Expression Expression { get; set; } public Debugger.Expressions.Expression Expression { get; set; }

12
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/AtomicType.cs

@ -16,6 +16,16 @@ namespace Debugger.AddIn.Visualizers.Utils
/// </summary> /// </summary>
public static class AtomicType public static class AtomicType
{ {
/// <summary>
/// Checks whether given expression's type is atomic.
/// </summary>
/// <param name="expr">Expression.</param>
/// <returns>True if expression's type is atomic, False otherwise.</returns>
public static bool IsAtomic(this DebugType type)
{
return !(type.IsClass || type.IsValueType /* = struct in C# */);
}
/// <summary> /// <summary>
/// Checks whether given expression's type is atomic. /// Checks whether given expression's type is atomic.
/// </summary> /// </summary>
@ -24,7 +34,7 @@ namespace Debugger.AddIn.Visualizers.Utils
public static bool IsOfAtomicType(this Expression expr) public static bool IsOfAtomicType(this Expression expr)
{ {
DebugType typeOfValue = expr.Evaluate(WindowsDebugger.CurrentProcess).Type; DebugType typeOfValue = expr.Evaluate(WindowsDebugger.CurrentProcess).Type;
return !(typeOfValue.IsClass || typeOfValue.IsValueType /* = struct in C# */); return AtomicType.IsAtomic(typeOfValue);
} }
} }
} }

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs

@ -64,7 +64,7 @@ namespace Debugger.AddIn.Visualizers.Utils
return int.Parse(defaultHashCode); return int.Parse(defaultHashCode);
} }
public static Value GetPermanentReference(this Expression expr) public static Value EvalPermanentReference(this Expression expr)
{ {
return expr.Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference(); return expr.Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference();
} }

Loading…
Cancel
Save