13 changed files with 526 additions and 183 deletions
@ -0,0 +1,34 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="ViewLocator.cs" company="Steven Kirk">
|
|||
// Copyright 2015 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Diagnostics |
|||
{ |
|||
using System; |
|||
using Perspex.Controls; |
|||
|
|||
internal class ViewLocator<TViewModel> : IDataTemplate |
|||
{ |
|||
public Control Build(object data) |
|||
{ |
|||
var name = data.GetType().FullName.Replace("ViewModel", "View"); |
|||
var type = Type.GetType(name); |
|||
|
|||
if (type != null) |
|||
{ |
|||
return (Control)Activator.CreateInstance(type); |
|||
} |
|||
else |
|||
{ |
|||
return new TextBlock { Text = name }; |
|||
} |
|||
} |
|||
|
|||
public bool Match(object data) |
|||
{ |
|||
return data is TViewModel; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="DevToolsViewModel.cs" company="Steven Kirk">
|
|||
// Copyright 2015 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Diagnostics.ViewModels |
|||
{ |
|||
using System; |
|||
using Perspex.Controls; |
|||
using ReactiveUI; |
|||
|
|||
internal class DevToolsViewModel : ReactiveObject |
|||
{ |
|||
private Control root; |
|||
|
|||
private LogicalTreeViewModel logicalTree; |
|||
|
|||
private VisualTreeViewModel visualTree; |
|||
|
|||
public DevToolsViewModel() |
|||
{ |
|||
this.WhenAnyValue(x => x.Root).Subscribe(x => |
|||
{ |
|||
this.LogicalTree = new LogicalTreeViewModel(root); |
|||
this.VisualTree = new VisualTreeViewModel(root); |
|||
}); |
|||
} |
|||
|
|||
public Control Root |
|||
{ |
|||
get { return this.root; } |
|||
set { this.RaiseAndSetIfChanged(ref this.root, value); } |
|||
} |
|||
|
|||
public LogicalTreeViewModel LogicalTree |
|||
{ |
|||
get { return this.logicalTree; } |
|||
private set { this.RaiseAndSetIfChanged(ref this.logicalTree, value); } |
|||
} |
|||
|
|||
public VisualTreeViewModel VisualTree |
|||
{ |
|||
get { return this.visualTree; } |
|||
private set { this.RaiseAndSetIfChanged(ref this.visualTree, value); } |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="LogicalTreeViewModel.cs" company="Steven Kirk">
|
|||
// Copyright 2015 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Diagnostics.ViewModels |
|||
{ |
|||
using System.Reactive.Linq; |
|||
using Perspex.Controls; |
|||
using ReactiveUI; |
|||
|
|||
internal class LogicalTreeViewModel : ReactiveObject |
|||
{ |
|||
private LogicalTreeNode selected; |
|||
|
|||
private ObservableAsPropertyHelper<ControlDetailsViewModel> details; |
|||
|
|||
public LogicalTreeViewModel(Control root) |
|||
{ |
|||
this.Nodes = LogicalTreeNode.Create(root); |
|||
this.details = this.WhenAnyValue(x => x.SelectedNode) |
|||
.Select(x => x != null ? new ControlDetailsViewModel(x.Control) : null) |
|||
.ToProperty(this, x => x.Details); |
|||
} |
|||
|
|||
public LogicalTreeNode[] Nodes { get; } |
|||
|
|||
public LogicalTreeNode SelectedNode |
|||
{ |
|||
get { return this.selected; } |
|||
set { this.RaiseAndSetIfChanged(ref this.selected, value); } |
|||
} |
|||
|
|||
public ControlDetailsViewModel Details |
|||
{ |
|||
get { return this.details.Value; } |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="VisualTreeViewModel.cs" company="Steven Kirk">
|
|||
// Copyright 2015 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Diagnostics.ViewModels |
|||
{ |
|||
using System.Reactive.Linq; |
|||
using Perspex.Controls; |
|||
using ReactiveUI; |
|||
|
|||
internal class VisualTreeViewModel : ReactiveObject |
|||
{ |
|||
private VisualTreeNode selected; |
|||
|
|||
private ObservableAsPropertyHelper<ControlDetailsViewModel> details; |
|||
|
|||
public VisualTreeViewModel(Control root) |
|||
{ |
|||
this.Nodes = VisualTreeNode.Create(root); |
|||
this.details = this.WhenAnyValue(x => x.SelectedNode) |
|||
.Select(x => x != null ? new ControlDetailsViewModel(x.Control) : null) |
|||
.ToProperty(this, x => x.Details); |
|||
} |
|||
|
|||
public VisualTreeNode[] Nodes { get; } |
|||
|
|||
public VisualTreeNode SelectedNode |
|||
{ |
|||
get { return this.selected; } |
|||
set { this.RaiseAndSetIfChanged(ref this.selected, value); } |
|||
} |
|||
|
|||
public ControlDetailsViewModel Details |
|||
{ |
|||
get { return this.details.Value; } |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="DevTools.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Diagnostics.Views |
|||
{ |
|||
using Perspex.Controls; |
|||
using Perspex.Diagnostics.ViewModels; |
|||
using ReactiveUI; |
|||
using System; |
|||
using System.Reactive.Linq; |
|||
|
|||
internal class ControlDetailsView : UserControl |
|||
{ |
|||
private static readonly PerspexProperty<ControlDetailsViewModel> ViewModelProperty = |
|||
PerspexProperty.Register<ControlDetailsView, ControlDetailsViewModel>("ViewModel"); |
|||
|
|||
public ControlDetailsView() |
|||
{ |
|||
this.InitializeComponent(); |
|||
this.GetObservable(DataContextProperty) |
|||
.Subscribe(x => this.ViewModel = (ControlDetailsViewModel)x); |
|||
} |
|||
|
|||
public ControlDetailsViewModel ViewModel |
|||
{ |
|||
get { return this.GetValue(ViewModelProperty); } |
|||
private set { this.SetValue(ViewModelProperty, value); } |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
this.Content = new ScrollViewer |
|||
{ |
|||
Content = new ItemsControl |
|||
{ |
|||
DataTemplates = new DataTemplates |
|||
{ |
|||
new DataTemplate<PropertyDetails>(x => |
|||
new StackPanel |
|||
{ |
|||
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 }, |
|||
}, |
|||
}), |
|||
}, |
|||
[!ItemsControl.ItemsProperty] = this.WhenAnyValue(x => x.ViewModel.Properties), |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="DevTools.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Diagnostics.Views |
|||
{ |
|||
using Perspex.Controls; |
|||
using Perspex.Diagnostics.ViewModels; |
|||
using ReactiveUI; |
|||
using System; |
|||
using System.Reactive.Linq; |
|||
|
|||
internal class LogicalTreeView : TreePage |
|||
{ |
|||
private static readonly PerspexProperty<LogicalTreeViewModel> ViewModelProperty = |
|||
PerspexProperty.Register<LogicalTreeView, LogicalTreeViewModel>("ViewModel"); |
|||
|
|||
public LogicalTreeView() |
|||
{ |
|||
this.InitializeComponent(); |
|||
this.GetObservable(DataContextProperty) |
|||
.Subscribe(x => this.ViewModel = (LogicalTreeViewModel)x); |
|||
} |
|||
|
|||
public LogicalTreeViewModel ViewModel |
|||
{ |
|||
get { return this.GetValue(ViewModelProperty); } |
|||
private set { this.SetValue(ViewModelProperty, value); } |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
TreeView tree; |
|||
|
|||
this.Content = new Grid |
|||
{ |
|||
ColumnDefinitions = new ColumnDefinitions |
|||
{ |
|||
new ColumnDefinition(1, GridUnitType.Star), |
|||
new ColumnDefinition(4, GridUnitType.Pixel), |
|||
new ColumnDefinition(3, GridUnitType.Star), |
|||
}, |
|||
Children = new Controls |
|||
{ |
|||
(tree = new TreeView |
|||
{ |
|||
DataTemplates = new DataTemplates |
|||
{ |
|||
new TreeDataTemplate<LogicalTreeNode>(this.GetHeader, x => x.Children), |
|||
}, |
|||
[!TreeView.ItemsProperty] = this.WhenAnyValue(x => x.ViewModel.Nodes), |
|||
}), |
|||
new GridSplitter |
|||
{ |
|||
[Grid.ColumnProperty] = 1, |
|||
Width = 4, |
|||
}, |
|||
new ContentControl |
|||
{ |
|||
[!ContentControl.ContentProperty] = this.WhenAnyValue(x => x.ViewModel.Details), |
|||
[Grid.ColumnProperty] = 2, |
|||
} |
|||
} |
|||
}; |
|||
|
|||
tree.GetObservable(TreeView.SelectedItemProperty) |
|||
.OfType<LogicalTreeNode>() |
|||
.Subscribe(x => this.ViewModel.SelectedNode = x); |
|||
} |
|||
|
|||
private Control GetHeader(LogicalTreeNode node) |
|||
{ |
|||
var result = new StackPanel |
|||
{ |
|||
Orientation = Orientation.Horizontal, |
|||
Gap = 8, |
|||
Children = new Controls |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Text = node.Type, |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
[!TextBlock.TextProperty] = node.WhenAnyValue(x => x.Classes), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
result.PointerEnter += this.AddAdorner; |
|||
result.PointerLeave += this.RemoveAdorner; |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="DevTools.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Diagnostics.Views |
|||
{ |
|||
using Perspex.Controls; |
|||
using Perspex.Controls.Primitives; |
|||
using Perspex.Controls.Shapes; |
|||
using Perspex.Diagnostics.ViewModels; |
|||
using Perspex.Input; |
|||
using Perspex.Media; |
|||
|
|||
internal class TreePage : UserControl |
|||
{ |
|||
private Control adorner; |
|||
|
|||
protected void AddAdorner(object sender, PointerEventArgs e) |
|||
{ |
|||
var node = (TreeNode)((Control)sender).DataContext; |
|||
var layer = AdornerLayer.GetAdornerLayer(node.Control); |
|||
|
|||
if (layer != null) |
|||
{ |
|||
this.adorner = new Rectangle |
|||
{ |
|||
Fill = new SolidColorBrush(0x80a0c5e8), |
|||
[AdornerLayer.AdornedElementProperty] = node.Control, |
|||
}; |
|||
|
|||
layer.Children.Add(this.adorner); |
|||
} |
|||
} |
|||
|
|||
protected void RemoveAdorner(object sender, PointerEventArgs e) |
|||
{ |
|||
if (this.adorner != null) |
|||
{ |
|||
((Panel)this.adorner.Parent).Children.Remove(this.adorner); |
|||
this.adorner = null; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,100 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="VisualTreeView.cs" company="Steven Kirk">
|
|||
// Copyright 2015 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Diagnostics.Views |
|||
{ |
|||
using System; |
|||
using System.Reactive.Linq; |
|||
using Perspex.Controls; |
|||
using Perspex.Diagnostics.ViewModels; |
|||
using Perspex.Media; |
|||
using ReactiveUI; |
|||
|
|||
internal class VisualTreeView : TreePage |
|||
{ |
|||
private static readonly PerspexProperty<VisualTreeViewModel> ViewModelProperty = |
|||
PerspexProperty.Register<VisualTreeView, VisualTreeViewModel>("ViewModel"); |
|||
|
|||
public VisualTreeView() |
|||
{ |
|||
this.InitializeComponent(); |
|||
this.GetObservable(DataContextProperty) |
|||
.Subscribe(x => this.ViewModel = (VisualTreeViewModel)x); |
|||
} |
|||
|
|||
public VisualTreeViewModel ViewModel |
|||
{ |
|||
get { return this.GetValue(ViewModelProperty); } |
|||
private set { this.SetValue(ViewModelProperty, value); } |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
TreeView tree; |
|||
|
|||
this.Content = new Grid |
|||
{ |
|||
ColumnDefinitions = new ColumnDefinitions |
|||
{ |
|||
new ColumnDefinition(1, GridUnitType.Star), |
|||
new ColumnDefinition(4, GridUnitType.Pixel), |
|||
new ColumnDefinition(3, GridUnitType.Star), |
|||
}, |
|||
Children = new Controls |
|||
{ |
|||
(tree = new TreeView |
|||
{ |
|||
DataTemplates = new DataTemplates |
|||
{ |
|||
new TreeDataTemplate<VisualTreeNode>(this.GetHeader, x => x.Children), |
|||
}, |
|||
[!TreeView.ItemsProperty] = this.WhenAnyValue(x => x.ViewModel.Nodes), |
|||
}), |
|||
new GridSplitter |
|||
{ |
|||
[Grid.ColumnProperty] = 1, |
|||
Width = 4, |
|||
}, |
|||
new ContentControl |
|||
{ |
|||
[!ContentControl.ContentProperty] = this.WhenAnyValue(x => x.ViewModel.Details), |
|||
[Grid.ColumnProperty] = 2, |
|||
} |
|||
} |
|||
}; |
|||
|
|||
tree.GetObservable(TreeView.SelectedItemProperty) |
|||
.OfType<VisualTreeNode>() |
|||
.Subscribe(x => this.ViewModel.SelectedNode = x); |
|||
} |
|||
|
|||
private Control GetHeader(VisualTreeNode node) |
|||
{ |
|||
var result = new StackPanel |
|||
{ |
|||
Orientation = Orientation.Horizontal, |
|||
Gap = 8, |
|||
Children = new Controls |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
FontStyle = node.IsInTemplate ? FontStyle.Italic : FontStyle.Normal, |
|||
Text = node.Type, |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
[!TextBlock.TextProperty] = node.WhenAnyValue(x => x.Classes), |
|||
} |
|||
} |
|||
}; |
|||
|
|||
result.PointerEnter += this.AddAdorner; |
|||
result.PointerLeave += this.RemoveAdorner; |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue