Browse Source

Implemented PositionedGraphNodeControl, displaying tree of properties instead of flat list.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4371 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Martin Koníček 17 years ago
parent
commit
0c8663d53a
  1. 96
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml
  2. 136
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/PositionedGraphNodeControl.xaml.cs
  3. 30
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/NestedNodeViewModel.cs
  4. 12
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraphNode.cs
  5. 1
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNodeProperty.cs
  6. 11
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PropertyNodeViewModel.cs
  7. 4
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs

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

@ -1,7 +1,95 @@ @@ -1,7 +1,95 @@
<UserControl x:Class="Debugger.AddIn.Visualizers.Graph.Drawing.PositionedGraphNodeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
</Grid>
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
>
<aero:SystemDropShadowChrome>
<Grid>
<ListView Name="listView" AlternationCount="2" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#ddeeff" Offset="0.0" />
<GradientStop Color="White" Offset="0.4" />
<GradientStop Color="White" Offset="0.8" />
</LinearGradientBrush>
</ListView.Background>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Margin" Value="0"></Setter>
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Focusable" Value="false" />
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Transparent"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Transparent"></Setter>
</Trigger>
<DataTrigger Binding="{Binding IsNested}" Value="True">
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="Foreground" Value="#666666"></Setter>
<Setter Property="FontStyle" Value="Italic"></Setter>
</DataTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Azure" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style>
<Setter Property="FrameworkElement.Visibility" Value="Collapsed"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridView.Columns>
<!-- Expand button (either property or nested) -->
<GridViewColumn Header="Plus" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<ToggleButton x:Name="Expander" Width="20" IsChecked="{Binding IsExpanded}" Click="NestedExpandButton_Click" Padding="0" Margin="0 0 6 0">+</ToggleButton>
<ToggleButton x:Name="PropertyExpander" Click="PropertyExpandButton_Click" Padding="0" Margin="0 0 6 0">+p</ToggleButton>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=HasChildren}" Value="False">
<Setter TargetName="Expander"
Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=ShowExpandPropertyButton}" Value="False">
<Setter TargetName="PropertyExpander"
Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!-- Name -->
<GridViewColumn Header="Name" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" MinWidth="100"></TextBlock>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!-- Text -->
<GridViewColumn Header="Value" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" MinWidth="100"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Grid>
</aero:SystemDropShadowChrome>
</UserControl>

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

@ -4,16 +4,20 @@ @@ -4,16 +4,20 @@
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version>
// </file>
using Debugger.AddIn.Visualizers.Graph.Layout;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using Debugger.AddIn.Visualizers.Graph.Layout;
using System;
using System.Collections.Generic;
using System.Linq;
using Debugger.AddIn.Visualizers.Common;
namespace Debugger.AddIn.Visualizers.Graph.Drawing
{
@ -22,7 +26,6 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -22,7 +26,6 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
/// </summary>
public partial class PositionedGraphNodeControl : UserControl
{
/*
/// <summary>
/// Occurs when a <see cref="PositionedNodeProperty"/> is expanded.
/// </summary>
@ -31,11 +34,134 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing @@ -31,11 +34,134 @@ namespace Debugger.AddIn.Visualizers.Graph.Drawing
/// Occurs when a <see cref="PositionedNodeProperty"/> is collaped.
/// </summary>
public event EventHandler<PositionedPropertyEventArgs> PropertyCollapsed;
*/
// shown in the ListView
private ObservableCollection<NestedNodeViewModel> view = new ObservableCollection<NestedNodeViewModel>();
private NestedNodeViewModel root;
/// <summary>
/// The tree to be displayed in this Control.
/// </summary>
public NestedNodeViewModel Root
{
get { return this.root; }
set
{
this.root = value;
this.view = initializeView(this.root);
// data virtualization, PropertyNodeViewModel implements IEvaluate
this.listView.ItemsSource = new VirtualizingObservableCollection<NestedNodeViewModel>(this.view);
//listView.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(listView_ScrollChanged));
}
}
public PositionedGraphNodeControl()
{
InitializeComponent();
}
private void PropertyExpandButton_Click(object sender, RoutedEventArgs e)
{
var clickedButton = (ToggleButton)e.Source;
PropertyNodeViewModel clickedNode = null;
try
{
clickedNode = (PropertyNodeViewModel)(clickedButton).DataContext;
}
catch(InvalidCastException)
{
throw new InvalidOperationException("Clicked property expand button, button shouln't be there - DataContext is not PropertyNodeViewModel.");
}
PositionedNodeProperty property = clickedNode.Property;
property.IsExpanded = !property.IsExpanded;
clickedButton.Content = property.IsExpanded ? "-p" : "+p";
if (property.IsExpanded)
{
OnPropertyExpanded(property);
}
else
{
OnPropertyCollapsed(property);
}
}
private void NestedExpandButton_Click(object sender, RoutedEventArgs e)
{
var clickedButton = (ToggleButton)e.Source;
var clickedNode = (NestedNodeViewModel)(clickedButton).DataContext;
int clickedIndex = this.view.IndexOf(clickedNode);
//clickedNode.IsExpanded = !clickedNode.IsExpanded; // done by data binding
clickedButton.Content = clickedNode.IsExpanded ? "-" : "+"; // could be done by a converter
if (clickedNode.IsExpanded)
{
// insert children
int i = 1;
foreach (var childNode in clickedNode.Children)
{
this.view.Insert(clickedIndex + i, childNode);
i++;
}
}
else
{
// remove whole subtree
int size = subtreeSize(clickedNode) - 1;
for (int i = 0; i < size; i++)
{
this.view.RemoveAt(clickedIndex + 1);
}
}
var a = new ListViewItem();
// set to Auto again to resize columns
var colName = (this.listView.View as GridView).Columns[0];
var colValue = (this.listView.View as GridView).Columns[1];
colName.Width = 300;
colName.Width = double.NaN;
colValue.Width = 300;
colValue.Width = double.NaN;
this.view.Insert(0, new NestedNodeViewModel());
this.view.RemoveAt(0);
this.listView.UpdateLayout();
this.listView.Width = colName.ActualWidth + colValue.ActualWidth + 30;
this.listView.Width = double.NaN;
}
private ObservableCollection<NestedNodeViewModel> initializeView(NestedNodeViewModel root)
{
var view = new ObservableCollection<NestedNodeViewModel>();
foreach (var topLevelNode in root.Children)
{
view.Add(topLevelNode);
}
return view;
}
private int subtreeSize(NestedNodeViewModel node)
{
return 1 + node.Children.Sum(child => (child.IsExpanded ? subtreeSize(child) : 1));
}
#region event helpers
protected virtual void OnPropertyExpanded(PositionedNodeProperty property)
{
if (this.PropertyExpanded != null)
{
this.PropertyExpanded(this, new PositionedPropertyEventArgs(property));
}
}
protected virtual void OnPropertyCollapsed(PositionedNodeProperty property)
{
if (this.PropertyCollapsed != null)
{
this.PropertyCollapsed(this, new PositionedPropertyEventArgs(property));
}
}
#endregion
}
}

30
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/NestedNodeViewModel.cs

@ -16,6 +16,9 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -16,6 +16,9 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
{
public string Name { get; set; }
public string Text { get; set; }
private List<NestedNodeViewModel> children = new List<NestedNodeViewModel>();
public List<NestedNodeViewModel> Children { get { return this.children; } }
/// <summary>
/// Is this expandable node?
@ -24,14 +27,33 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -24,14 +27,33 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
/// <summary>
/// Does this node have any children?
/// </summary>
public bool HasChildren { get; set; }
public bool HasChildren { get { return this.Children.Count > 0; } }
/// <summary>
/// Show a button to expand property associated with this node?
/// </summary>
public bool ShowExpandPropertyButton
{
get
{
var thisAsPropertyNode = this as PropertyNodeViewModel;
if (thisAsPropertyNode == null)
{
// 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);
}
}
}
// if we bound this ViewModel to a TreeView, this would not be needed,
// it is added "artificially", to support PositionedGraphNodeControl
public bool IsExpanded { get; set; }
private List<NestedNodeViewModel> children = new List<NestedNodeViewModel>();
public List<NestedNodeViewModel> Children { get { return this.children; } }
public NestedNodeViewModel()
{

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

@ -25,8 +25,8 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -25,8 +25,8 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
get { return objectNode; }
}
public event EventHandler<PositionedPropertyEventArgs> Expanded;
public event EventHandler<PositionedPropertyEventArgs> Collapsed;
public event EventHandler<PositionedPropertyEventArgs> PropertyExpanded;
public event EventHandler<PositionedPropertyEventArgs> PropertyCollapsed;
private List<PositionedNodeProperty> properties = new List<PositionedNodeProperty>();
public List<PositionedNodeProperty> Properties
@ -127,17 +127,17 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -127,17 +127,17 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
#region event helpers
protected virtual void OnPropertyExpanded(object sender, PositionedPropertyEventArgs propertyArgs)
{
if (this.Expanded != null)
if (this.PropertyExpanded != null)
{
this.Expanded(sender, propertyArgs);
this.PropertyExpanded(sender, propertyArgs);
}
}
protected virtual void OnPropertyCollapsed(object sender, PositionedPropertyEventArgs propertyArgs)
{
if (this.Collapsed != null)
if (this.PropertyCollapsed != null)
{
this.Collapsed(sender, propertyArgs);
this.PropertyCollapsed(sender, propertyArgs);
}
}
#endregion

1
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNodeProperty.cs

@ -10,6 +10,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -10,6 +10,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
{
/// <summary>
/// <see cref="ObjectProperty"/> with outgoing <see cref="PositionedEdge"/>.
/// Implements evaluation of value on demand using IEvaluate.
/// </summary>
public class PositionedNodeProperty : IEvaluate
{

11
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PropertyNodeViewModel.cs

@ -17,9 +17,20 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout @@ -17,9 +17,20 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
public PropertyNodeViewModel(PositionedNodeProperty positionedNodeProperty)
{
if (positionedNodeProperty == null)
throw new ArgumentNullException("positionedNodeProperty");
this.positionedProperty = positionedNodeProperty;
}
/// <summary>
/// The PositionedNodeProperty this node contains.
/// </summary>
public PositionedNodeProperty Property
{
get { return this.positionedProperty; }
}
public bool IsEvaluated
{
get { return this.positionedProperty.IsEvaluated; }

4
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs

@ -141,8 +141,8 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -141,8 +141,8 @@ namespace Debugger.AddIn.Visualizers.Graph
{
foreach (var node in posGraph.Nodes)
{
node.Expanded += new EventHandler<PositionedPropertyEventArgs>(node_Expanded);
node.Collapsed += new EventHandler<PositionedPropertyEventArgs>(node_Collapsed);
node.PropertyExpanded += new EventHandler<PositionedPropertyEventArgs>(node_Expanded);
node.PropertyCollapsed += new EventHandler<PositionedPropertyEventArgs>(node_Collapsed);
}
}

Loading…
Cancel
Save