Browse Source

Added diagnostic popup to devtools.

pull/58/head
Steven Kirk 11 years ago
parent
commit
8d7d04ffd3
  1. 35
      Perspex.Base/Diagnostics/PerspexObjectExtensions.cs
  2. 12
      Perspex.Base/Diagnostics/PerspexPropertyValue.cs
  3. 1
      Perspex.Base/Perspex.Base.csproj
  4. 52
      Perspex.Base/PerspexObject.cs
  5. 2
      Perspex.Base/PerspexProperty.cs
  6. 42
      Perspex.Base/PriorityValue.cs
  7. 23
      Perspex.Diagnostics/Debug.cs
  8. 4
      Perspex.Diagnostics/ViewModels/ControlDetailsViewModel.cs
  9. 55
      Perspex.Diagnostics/ViewModels/PropertyDetails.cs
  10. 10
      Perspex.Diagnostics/Views/ControlDetailsView.cs

35
Perspex.Base/Diagnostics/PerspexObjectExtensions.cs

@ -0,0 +1,35 @@
// --------------------------------------------------------------------
// <copyright file="PerspexObjectExtensions.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Diagnostics
{
public static class PerspexObjectExtensions
{
public static PerspexPropertyValue GetDiagnostic(this PerspexObject o, PerspexProperty property)
{
var set = o.GetSetValues();
PriorityValue value;
if (set.TryGetValue(property, out value))
{
return new PerspexPropertyValue(
property,
value.Value,
(BindingPriority)value.ValuePriority,
value.GetDiagnostic());
}
else
{
return new PerspexPropertyValue(
property,
o.GetValue(property),
BindingPriority.Unset,
"Unset");
}
}
}
}

12
Perspex.Base/Diagnostics/PerspexPropertyValue.cs

@ -11,17 +11,21 @@ namespace Perspex.Diagnostics
public PerspexPropertyValue(
PerspexProperty property,
object value,
BindingPriority priority)
BindingPriority priority,
string diagnostic)
{
this.Property = property;
this.Value = value;
this.Priority = priority;
this.Diagnostic = diagnostic;
}
public PerspexProperty Property { get; private set; }
public PerspexProperty Property { get; }
public object Value { get; private set; }
public object Value { get; }
public BindingPriority Priority { get; private set; }
public BindingPriority Priority { get; }
public string Diagnostic { get; }
}
}

1
Perspex.Base/Perspex.Base.csproj

@ -37,6 +37,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="Binding.cs" />
<Compile Include="Diagnostics\PerspexObjectExtensions.cs" />
<Compile Include="PriorityBindingEntry.cs" />
<Compile Include="Collections\IPerspexList.cs" />
<Compile Include="Collections\PerspexReadOnlyListView.cs" />

52
Perspex.Base/PerspexObject.cs

@ -409,35 +409,6 @@ namespace Perspex
return (T)this.GetValue((PerspexProperty)property);
}
/// <summary>
/// Gets the value of of all properties that are registered on this object.
/// </summary>
/// <returns>
/// A collection of <see cref="PerspexPropertyValue"/> objects.
/// </returns>
public IEnumerable<PerspexPropertyValue> GetAllValues()
{
foreach (PerspexProperty property in this.GetRegisteredProperties())
{
PriorityValue value;
if (this.values.TryGetValue(property, out value))
{
yield return new PerspexPropertyValue(
property,
value.Value,
(BindingPriority)value.ValuePriority);
}
else
{
yield return new PerspexPropertyValue(
property,
this.GetValue(property),
BindingPriority.Unset);
}
}
}
/// <summary>
/// Gets all properties that are registered on this object.
/// </summary>
@ -464,20 +435,6 @@ namespace Perspex
}
}
/// <summary>
/// Gets all of the <see cref="PerspexProperty"/> values explicitly set on this object.
/// </summary>
public IEnumerable<PerspexPropertyValue> GetSetValues()
{
foreach (var value in this.values)
{
yield return new PerspexPropertyValue(
value.Key,
value.Value.Value,
(BindingPriority)value.Value.ValuePriority);
}
}
/// <summary>
/// Checks whether a <see cref="PerspexProperty"/> is set on this object.
/// </summary>
@ -681,6 +638,15 @@ namespace Perspex
}
}
/// <summary>
/// Gets all priority values set on the object.
/// </summary>
/// <returns>A collection of property/value tuples.</returns>
internal IDictionary<PerspexProperty, PriorityValue> GetSetValues()
{
return this.values;
}
/// <summary>
/// Forces re-coercion of properties when a property value changes.
/// </summary>

2
Perspex.Base/PerspexProperty.cs

@ -361,7 +361,7 @@ namespace Perspex
{
public override string ToString()
{
return "{Unset}";
return "(unset)";
}
}
}

42
Perspex.Base/PriorityValue.cs

@ -11,7 +11,7 @@ namespace Perspex
using System.Linq;
using System.Reactive.Subjects;
using System.Reflection;
using Perspex.Diagnostics;
using System.Text;
/// <summary>
/// Maintains a list of prioritised bindings together with a current value.
@ -171,6 +171,46 @@ namespace Perspex
}
}
/// <summary>
/// Returns diagnostic string that can help the user debug the bindings in effect on
/// this object.
/// </summary>
/// <returns>A diagnostic string.</returns>
public string GetDiagnostic()
{
var b = new StringBuilder();
var first = true;
foreach (var level in this.levels)
{
if (!first)
{
b.AppendLine();
}
b.Append(this.ValuePriority == level.Key ? "*" : "");
b.Append("Priority ");
b.Append(level.Key);
b.Append(": ");
b.AppendLine(level.Value.Value?.ToString() ?? "(null)");
b.AppendLine("--------");
b.Append("Direct: ");
b.AppendLine(level.Value.DirectValue.ToString());
foreach (var binding in level.Value.Bindings)
{
b.Append(level.Value.ActiveBindingIndex == binding.Index ? "*" : "");
b.Append(binding.Description ?? binding.Observable.GetType().Name);
b.Append(": ");
b.AppendLine(binding.Value.ToString());
}
first = false;
}
return b.ToString();
}
/// <summary>
/// Causes a re-coercion of the value.
/// </summary>

23
Perspex.Diagnostics/Debug.cs

@ -40,16 +40,21 @@ namespace Perspex.Diagnostics
builder.Append(" ");
builder.AppendLine(control.Classes.ToString());
foreach (var value in control.GetSetValues())
foreach (var property in control.GetRegisteredProperties())
{
builder.Append(Indent(indent));
builder.Append(" | ");
builder.Append(value.Property.Name);
builder.Append(" = ");
builder.Append(value.Value ?? "(null)");
builder.Append(" [");
builder.Append(value.Priority);
builder.AppendLine("]");
var value = control.GetDiagnostic(property);
if (value.Priority != BindingPriority.Unset)
{
builder.Append(Indent(indent));
builder.Append(" | ");
builder.Append(value.Property.Name);
builder.Append(" = ");
builder.Append(value.Value ?? "(null)");
builder.Append(" [");
builder.Append(value.Priority);
builder.AppendLine("]");
}
}
}
else

4
Perspex.Diagnostics/ViewModels/ControlDetailsViewModel.cs

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

55
Perspex.Diagnostics/ViewModels/PropertyDetails.cs

@ -13,32 +13,43 @@ namespace Perspex.Diagnostics.ViewModels
{
private object value;
public PropertyDetails(PerspexPropertyValue value)
private string priority;
private string diagnostic;
public PropertyDetails(PerspexObject o, PerspexProperty property)
{
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.Value ?? "(null)";
this.Priority = (value.Priority != BindingPriority.Unset) ?
value.Priority.ToString() :
value.Property.Inherits ? "Inherited" : "Unset";
//if (value.PriorityValue != null)
//{
// value.PriorityValue.Changed.Subscribe(x => this.Value = x.Item2);
//}
this.Name = property.IsAttached ?
string.Format("[{0}.{1}]", property.OwnerType.Name, property.Name) :
property.Name;
this.IsAttached = property.IsAttached;
// TODO: Unsubscribe when view model is deactivated.
o.GetObservable(property).Subscribe(x =>
{
var diagnostic = o.GetDiagnostic(property);
this.Value = diagnostic.Value ?? "(null)";
this.Priority = (diagnostic.Priority != BindingPriority.Unset) ?
diagnostic.Priority.ToString() :
diagnostic.Property.Inherits ? "Inherited" : "Unset";
this.Diagnostic = diagnostic.Diagnostic;
});
}
public string Name
public string Name { get; }
public bool IsAttached { get; }
public string Priority
{
get;
get { return this.priority; }
private set { this.RaiseAndSetIfChanged(ref this.priority, value); }
}
public bool IsAttached
public string Diagnostic
{
get;
get { return this.diagnostic; }
private set { this.RaiseAndSetIfChanged(ref this.diagnostic, value); }
}
public object Value
@ -46,11 +57,5 @@ namespace Perspex.Diagnostics.ViewModels
get { return this.value; }
private set { this.RaiseAndSetIfChanged(ref this.value, value); }
}
public string Priority
{
get;
private set;
}
}
}

10
Perspex.Diagnostics/Views/ControlDetailsView.cs

@ -55,7 +55,7 @@ namespace Perspex.Diagnostics.Views
{
new Setter(Control.MarginProperty, new Thickness(2)),
}
}
},
},
[GridRepeater.TemplateProperty] = pt,
[!GridRepeater.ItemsProperty] = this.WhenAnyValue(x => x.ViewModel.Properties),
@ -69,7 +69,8 @@ namespace Perspex.Diagnostics.Views
yield return new TextBlock
{
Text = property.Name
Text = property.Name,
[!ToolTip.TipProperty] = property.WhenAnyValue(x => x.Diagnostic),
};
yield return new TextBlock
@ -77,7 +78,10 @@ namespace Perspex.Diagnostics.Views
[!TextBlock.TextProperty] = property.WhenAnyValue(v => v.Value).Select(v => v?.ToString()),
};
yield return new TextBlock { Text = property.Priority };
yield return new TextBlock
{
[!TextBlock.TextProperty] = property.WhenAnyValue(x => x.Priority),
};
}
}
}

Loading…
Cancel
Save