Browse Source

Object graph - rewrote calculation of node size. Now arrows fit.

pull/15/head
mkonicek 15 years ago
parent
commit
fac118b615
  1. 30
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/VirtualizingObservableCollection.cs
  2. 6
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml
  3. 54
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml.cs
  4. 11
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/PositionedNode.cs
  5. 2
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/Tree/TreeLayout.cs

30
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/VirtualizingObservableCollection.cs

@ -5,31 +5,33 @@ using System; @@ -5,31 +5,33 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Debugger.AddIn.Visualizers.Common
{
/// <summary>
/// Wrapper of ObservableCollection&lt;IEvaluate&gt;
/// with lazy indexer, suitable for Controls that use indexer to query for data as needed (eg. ListView).
/// Proxy wrapping ObservableCollection&lt;IEvaluate&gt;
/// with lazy indexer, suitable for Controls that use indexer to query data as needed (eg. ListView).
/// </summary>
public class VirtualizingObservableCollection<T> : ObservableCollection<T>, IList<T>, IList
{
ObservableCollection<T> lazifiedCollection;
ObservableCollection<T> collection;
public VirtualizingObservableCollection(ObservableCollection<T> lazifiedCollection)
public VirtualizingObservableCollection(ObservableCollection<T> collection)
{
this.lazifiedCollection = lazifiedCollection;
this.lazifiedCollection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(lazifiedCollection_CollectionChanged);
this.collection = collection;
this.collection.CollectionChanged += UnderlyingCollection_Changed;
}
void lazifiedCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
void UnderlyingCollection_Changed(object sender, NotifyCollectionChangedEventArgs e)
{
// Notify when someone changes the underlying collection, so that UI always stays in sync
OnCollectionChanged(e);
}
public new int Count
{
get { return this.lazifiedCollection.Count; }
get { return this.collection.Count; }
}
/// <summary>
@ -39,16 +41,12 @@ namespace Debugger.AddIn.Visualizers.Common @@ -39,16 +41,12 @@ namespace Debugger.AddIn.Visualizers.Common
{
get
{
var underlyingItem = this.lazifiedCollection[index];
var underlyingItem = this.collection[index];
IEvaluate itemLazy = underlyingItem as IEvaluate;
if (itemLazy != null)
{
if (!itemLazy.IsEvaluated)
{
itemLazy.Evaluate();
}
if (itemLazy != null && (!itemLazy.IsEvaluated)) {
itemLazy.Evaluate();
}
// return item, evaluated if it was IEvaluate
// return evaluated items
return underlyingItem;
}
set

6
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml

@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
<Border Background="#ddeeff" BorderThickness="1,1,1,0" BorderBrush="DarkGray" HorizontalAlignment="Stretch" Padding="1">
<TextBlock>Hello</TextBlock>
</Border> -->
<ListView Name="listView" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView Name="listView" ScrollViewer.VerticalScrollBarVisibility="Auto" Width="200" Height="300">
<ListView.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#ddeeff" Offset="0.0" />
@ -85,7 +85,7 @@ @@ -85,7 +85,7 @@
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!-- Name -->
<GridViewColumn Header="Name" Width="Auto">
<GridViewColumn Header="Name" Width="60">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
@ -95,7 +95,7 @@ @@ -95,7 +95,7 @@
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!-- Text -->
<GridViewColumn Header="Value " Width="Auto" CellTemplate="{StaticResource valueColumnTemplate}">
<GridViewColumn Header="Value" Width="60" CellTemplate="{StaticResource valueColumnTemplate}">
</GridViewColumn>
</GridView.Columns>
</GridView>

54
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml.cs

@ -46,7 +46,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -46,7 +46,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
// shown in the ListView
private ObservableCollection<ContentNode> view = new ObservableCollection<ContentNode>();
private ObservableCollection<ContentNode> items = new ObservableCollection<ContentNode>();
private ContentNode root;
/// <summary>
@ -55,19 +55,11 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -55,19 +55,11 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
public ContentNode Root
{
get { return this.root; }
set
{
set {
this.root = value;
this.view = getInitialView(this.root);
this.items = GetInitialItems(this.root);
// data virtualization, ContentPropertyNode implements IEvaluate
this.listView.ItemsSource = new VirtualizingObservableCollection<ContentNode>(this.view);
/*int maxLen = this.view.MaxOrDefault(contentNode => { return contentNode.Name.Length; }, 0);
int spaces = Math.Max((int)(maxLen * 1.8 - 3), 0);
string addedSpaces = StringHelper.Repeat(' ', spaces);
GridView gv = listView.View as GridView;
// hack - autosize Name column
gv.Columns[1].Header = "Name" + addedSpaces;*/
this.listView.ItemsSource = new VirtualizingObservableCollection<ContentNode>(this.items);
//AutoSizeColumns();
@ -108,14 +100,28 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -108,14 +100,28 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
}
}
public PositionedGraphNodeControl()
public void CalculateWidthHeight()
{
InitializeComponent();
Init();
int maxLen = this.items.MaxOrDefault(contentNode => contentNode.Name.Length, 0);
int spaces = Math.Max((int)(maxLen * 1.8 - 3), 0);
GridView gv = listView.View as GridView;
gv.Columns[1].Width = 50 + spaces * 2.5;
gv.Columns[2].Width = 80;
listView.Width = gv.Columns[0].Width + gv.Columns[1].Width + gv.Columns[2].Width + 10;
int maxItems = 10;
listView.Height = Math.Min(this.items.Count, maxItems) * 20;
if (this.items.Count > maxItems) {
listView.Width += 30; // for scrollbar
}
this.Width = listView.Width + 2;
this.Height = listView.Height + 2;
}
public void Init()
public PositionedGraphNodeControl()
{
InitializeComponent();
PropertyExpanded = null;
PropertyCollapsed = null;
ContentNodeExpanded = null;
@ -165,7 +171,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -165,7 +171,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
{
var clickedButton = (ToggleButton)e.Source;
var clickedNode = (ContentNode)(clickedButton).DataContext;
int clickedIndex = this.view.IndexOf(clickedNode);
int clickedIndex = this.items.IndexOf(clickedNode);
//clickedNode.IsExpanded = !clickedNode.IsExpanded; // done by data binding
clickedButton.Content = clickedNode.IsExpanded ? "-" : "+"; // could be done by a converter
@ -175,7 +181,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -175,7 +181,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
int i = 1;
foreach (var childNode in clickedNode.Children)
{
this.view.Insert(clickedIndex + i, childNode);
this.items.Insert(clickedIndex + i, childNode);
i++;
}
// insertChildren(clickedNode, this.view, clickedIndex); // TODO
@ -184,14 +190,16 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -184,14 +190,16 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
else
{
// remove whole subtree
int size = subtreeSize(clickedNode) - 1;
int size = SubtreeSize(clickedNode) - 1;
for (int i = 0; i < size; i++)
{
this.view.RemoveAt(clickedIndex + 1);
this.items.RemoveAt(clickedIndex + 1);
}
OnContentNodeCollapsed(clickedNode);
}
CalculateWidthHeight();
//AutoSizeColumns();
// set to Auto again to resize columns
@ -208,14 +216,14 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -208,14 +216,14 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
this.listView.Width = double.NaN;*/
}
private ObservableCollection<ContentNode> getInitialView(ContentNode root)
ObservableCollection<ContentNode> GetInitialItems(ContentNode root)
{
return new ObservableCollection<ContentNode>(root.FlattenChildrenExpanded());
}
private int subtreeSize(ContentNode node)
int SubtreeSize(ContentNode node)
{
return 1 + node.Children.Sum(child => (child.IsExpanded ? subtreeSize(child) : 1));
return 1 + node.Children.Sum(child => (child.IsExpanded ? SubtreeSize(child) : 1));
}
#region event helpers

11
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/PositionedNode.cs

@ -90,11 +90,11 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -90,11 +90,11 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
public double Top { get; set; }
public double Width
{
get { return NodeVisualControl.DesiredSize.Width; }
get { return NodeVisualControl.Width; }
}
public double Height
{
get { return NodeVisualControl.DesiredSize.Height; }
get { return NodeVisualControl.Height; }
}
public Point LeftTop
@ -142,5 +142,12 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -142,5 +142,12 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
box = new SplineRouting.Box(this);
return box.Inflated(padding);
}
public void MeasureVisualControl()
{
if ((this.NodeVisualControl != null)) {
this.NodeVisualControl.CalculateWidthHeight();
}
}
}
}

2
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/Tree/TreeLayout.cs

@ -52,6 +52,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -52,6 +52,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
foreach (ObjectGraphNode objectNode in objectGraph.ReachableNodes) {
var posNode = new PositionedNode(objectNode);
posNode.InitContentFromObjectNode(expanded);
posNode.MeasureVisualControl();
positionedGraph.AddNode(posNode);
positionedNodeFor[objectNode] = posNode;
}
@ -100,7 +101,6 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -100,7 +101,6 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
}
}
}
root.Measure();
root.SubtreeSize = Math.Max(GetLateralSizeWithMargin(root), subtreeSize);
}

Loading…
Cancel
Save