Browse Source

Improved DevTools a bit.

pull/58/head
Steven Kirk 11 years ago
parent
commit
9a82daac91
  1. 82
      Perspex.Base/PerspexProperty.cs
  2. 1
      Perspex.Diagnostics/Perspex.Diagnostics.csproj
  3. 5
      Perspex.Diagnostics/ViewModels/ControlDetailsViewModel.cs
  4. 12
      Perspex.Diagnostics/ViewModels/PropertyDetails.cs
  5. 52
      Perspex.Diagnostics/Views/ControlDetailsView.cs
  6. 72
      Perspex.Diagnostics/Views/GridRepeater.cs

82
Perspex.Base/PerspexProperty.cs

@ -54,9 +54,10 @@ namespace Perspex
Type valueType,
Type ownerType,
object defaultValue,
bool inherits,
BindingMode defaultBindingMode,
Func<PerspexObject, object, object> coerce)
bool inherits = false,
BindingMode defaultBindingMode = BindingMode.Default,
Func<PerspexObject, object, object> coerce = null,
bool isAttached = false)
{
Contract.Requires<NullReferenceException>(name != null);
Contract.Requires<NullReferenceException>(valueType != null);
@ -69,38 +70,44 @@ namespace Perspex
this.Inherits = inherits;
this.DefaultBindingMode = defaultBindingMode;
this.Coerce = coerce;
this.IsAttached = isAttached;
}
/// <summary>
/// Gets the name of the property.
/// </summary>
public string Name { get; private set; }
public string Name { get; }
/// <summary>
/// Gets the type of the property's value.
/// </summary>
public Type PropertyType { get; private set; }
public Type PropertyType { get; }
/// <summary>
/// Gets the type of the class that registers the property.
/// </summary>
public Type OwnerType { get; private set; }
public Type OwnerType { get; }
/// <summary>
/// Gets a value indicating whether the property inherits its value.
/// </summary>
public bool Inherits { get; private set; }
public bool Inherits { get; }
/// <summary>
/// Gets the default binding mode for the property.
/// </summary>
/// <returns></returns>
public BindingMode DefaultBindingMode { get; private set; }
public BindingMode DefaultBindingMode { get; }
/// <summary>
/// Gets the property's coerce function.
/// </summary>
public Func<PerspexObject, object, object> Coerce { get; private set; }
public Func<PerspexObject, object, object> Coerce { get; }
/// <summary>
/// Gets a value indicating whether this is an attached property.
/// </summary>
public bool IsAttached { get; }
/// <summary>
/// Gets an observable that is fired when this property is initialized on a
@ -153,7 +160,8 @@ namespace Perspex
defaultValue,
inherits,
defaultBindingMode,
coerce);
coerce,
false);
PerspexObject.Register(typeof(TOwner), result);
@ -182,12 +190,49 @@ namespace Perspex
Contract.Requires<NullReferenceException>(name != null);
PerspexProperty<TValue> result = new PerspexProperty<TValue>(
typeof(TOwner) + "." + name,
name,
typeof(TOwner),
defaultValue,
inherits,
defaultBindingMode,
coerce);
coerce,
true);
PerspexObject.Register(typeof(THost), result);
return result;
}
/// <summary>
/// Registers an attached <see cref="PerspexProperty"/>.
/// </summary>
/// <typeparam name="THost">The type of the class that the property is to be registered on.</typeparam>
/// <typeparam name="TValue">The type of the property's value.</typeparam>
/// <param name="name">The name of the property.</param>
/// <param name="ownerType">The type of the class that is registering the property.</param>
/// <param name="defaultValue">The default value of the property.</param>
/// <param name="inherits">Whether the property inherits its value.</param>
/// <param name="defaultBindingMode">The default binding mode for the property.</param>
/// <param name="coerce">A coercion function.</param>
/// <returns>A <see cref="PerspexProperty{TValue}"/></returns>
public static PerspexProperty<TValue> RegisterAttached<THost, TValue>(
string name,
Type ownerType,
TValue defaultValue = default(TValue),
bool inherits = false,
BindingMode defaultBindingMode = BindingMode.OneWay,
Func<PerspexObject, TValue, TValue> coerce = null)
{
Contract.Requires<NullReferenceException>(name != null);
PerspexProperty<TValue> result = new PerspexProperty<TValue>(
name,
ownerType,
defaultValue,
inherits,
defaultBindingMode,
coerce,
true);
PerspexObject.Register(typeof(THost), result);
@ -335,13 +380,15 @@ namespace Perspex
/// <param name="inherits">Whether the property inherits its value.</param>
/// <param name="defaultBindingMode">The default binding mode for the property.</param>
/// <param name="coerce">A coercion function.</param>
/// <param name="isAttached">Whether the property is an attached property.</param>
public PerspexProperty(
string name,
Type ownerType,
TValue defaultValue,
bool inherits,
BindingMode defaultBindingMode,
Func<PerspexObject, TValue, TValue> coerce)
TValue defaultValue = default(TValue),
bool inherits = false,
BindingMode defaultBindingMode = BindingMode.Default,
Func<PerspexObject, TValue, TValue> coerce = null,
bool isAttached = false)
: base(
name,
typeof(TValue),
@ -349,7 +396,8 @@ namespace Perspex
defaultValue,
inherits,
defaultBindingMode,
Convert(coerce))
Convert(coerce),
isAttached)
{
Contract.Requires<NullReferenceException>(name != null);
Contract.Requires<NullReferenceException>(ownerType != null);

1
Perspex.Diagnostics/Perspex.Diagnostics.csproj

@ -84,6 +84,7 @@
<Compile Include="ViewModels\TreeNode.cs" />
<Compile Include="ViewModels\VisualTreeNode.cs" />
<Compile Include="Views\ControlDetailsView.cs" />
<Compile Include="Views\GridRepeater.cs" />
<Compile Include="Views\VisualTreeView.cs" />
<Compile Include="Views\LogicalTreeView.cs" />
<Compile Include="Views\TreePage.cs" />

5
Perspex.Diagnostics/ViewModels/ControlDetailsViewModel.cs

@ -18,8 +18,9 @@ namespace Perspex.Diagnostics.ViewModels
if (control != null)
{
this.Properties = control.GetAllValues()
.Select(x => new PropertyDetails(x))
.OrderBy(x => x.Name);
.Select(x => new PropertyDetails(x))
.OrderBy(x => x.Name)
.OrderBy(x => x.IsAttached);
}
}

12
Perspex.Diagnostics/ViewModels/PropertyDetails.cs

@ -15,7 +15,11 @@ namespace Perspex.Diagnostics.ViewModels
public PropertyDetails(PerspexPropertyValue value)
{
this.Name = value.Property.Name;
this.Name = value.Property.IsAttached ?
string.Format("[{0}.{1}]", value.Property.OwnerType.Name, value.Property.Name) :
value.Property.Name;
this.IsAttached = value.Property.IsAttached;
this.value = value.CurrentValue ?? "(null)";
this.Priority = (value.PriorityValue != null) ?
Enum.GetName(typeof(BindingPriority), value.PriorityValue.ValuePriority) :
@ -30,7 +34,11 @@ namespace Perspex.Diagnostics.ViewModels
public string Name
{
get;
private set;
}
public bool IsAttached
{
get;
}
public object Value

52
Perspex.Diagnostics/Views/ControlDetailsView.cs

@ -8,8 +8,11 @@ namespace Perspex.Diagnostics.Views
{
using Perspex.Controls;
using Perspex.Diagnostics.ViewModels;
using Perspex.Styling;
using ReactiveUI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reactive.Linq;
internal class ControlDetailsView : UserControl
@ -32,28 +35,49 @@ namespace Perspex.Diagnostics.Views
private void InitializeComponent()
{
Func<object, IEnumerable<Control>> pt = this.PropertyTemplate;
this.Content = new ScrollViewer
{
Content = new ItemsControl
Content = new Grid
{
DataTemplates = new DataTemplates
ColumnDefinitions = new ColumnDefinitions
{
new ColumnDefinition(GridLength.Auto),
new ColumnDefinition(GridLength.Auto),
new ColumnDefinition(GridLength.Auto),
},
Styles = new Styles
{
new DataTemplate<PropertyDetails>(x =>
new StackPanel
new Style(x => x.Is<Control>())
{
Setters = new[]
{
Gap = 16,
Orientation = Orientation.Horizontal,
Children = new Controls
{
new TextBlock { Text = x.Name },
new TextBlock { [!TextBlock.TextProperty] = x.WhenAnyValue(v => v.Value).Select(v => v?.ToString()) },
new TextBlock { Text = x.Priority },
},
}),
new Setter(Control.MarginProperty, new Thickness(2)),
}
}
},
[!ItemsControl.ItemsProperty] = this.WhenAnyValue(x => x.ViewModel.Properties),
[GridRepeater.TemplateProperty] = pt,
[!GridRepeater.ItemsProperty] = this.WhenAnyValue(x => x.ViewModel.Properties),
}
};
}
private IEnumerable<Control> PropertyTemplate(object i)
{
var property = (PropertyDetails)i;
yield return new TextBlock
{
Text = property.Name
};
yield return new TextBlock
{
[!TextBlock.TextProperty] = property.WhenAnyValue(v => v.Value).Select(v => v?.ToString()),
};
yield return new TextBlock { Text = property.Priority };
}
}
}

72
Perspex.Diagnostics/Views/GridRepeater.cs

@ -0,0 +1,72 @@
// -----------------------------------------------------------------------
// <copyright file="VisualTreeView.cs" company="Steven Kirk">
// Copyright 2015 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Diagnostics.Views
{
using Perspex.Controls;
using Perspex.Controls.Templates;
using System;
using System.Collections;
using System.Collections.Generic;
internal static class GridRepeater
{
public static readonly PerspexProperty<IEnumerable> ItemsProperty =
PerspexProperty.RegisterAttached<Grid, IEnumerable>("Items", typeof(GridRepeater));
public static readonly PerspexProperty<Func<object, IEnumerable<Control>>> TemplateProperty =
PerspexProperty.RegisterAttached<Grid, Func<object, IEnumerable<Control>>>("Template", typeof(GridRepeater));
static GridRepeater()
{
ItemsProperty.Changed.Subscribe(ItemsChanged);
}
private static void ItemsChanged(PerspexPropertyChangedEventArgs e)
{
var grid = (Grid)e.Sender;
var items = (IEnumerable)e.NewValue;
var template = grid.GetValue(TemplateProperty);
grid.Children.Clear();
if (items != null)
{
int count = 0;
int cols = grid.ColumnDefinitions.Count;
foreach (var item in items)
{
foreach (var control in template(item))
{
grid.Children.Add(control);
Grid.SetColumn(control, count % cols);
Grid.SetRow(control, count / cols);
++count;
}
}
int rows = (int)Math.Ceiling((double)count / cols);
int difference = rows - grid.RowDefinitions.Count;
if (difference > 0)
{
for (int i = 0; i < difference; ++i)
{
grid.RowDefinitions.Add(new RowDefinition(GridLength.Auto));
}
}
else if (difference < 0)
{
for (int i = 0; i < difference; ++i)
{
grid.RowDefinitions.RemoveAt(grid.RowDefinitions.Count - 1);
}
}
}
}
}
}
Loading…
Cancel
Save