diff --git a/src/Perspex.Diagnostics/DevTools.paml.cs b/src/Perspex.Diagnostics/DevTools.paml.cs index ab374f09f1..3b96ebcf5a 100644 --- a/src/Perspex.Diagnostics/DevTools.paml.cs +++ b/src/Perspex.Diagnostics/DevTools.paml.cs @@ -19,6 +19,7 @@ namespace Perspex.Diagnostics InitializeComponent(); Root = root; DataContext = new DevToolsViewModel(root); + Root.PointerMoved += RootPointerMoved; } public IControl Root { get; } @@ -76,5 +77,16 @@ namespace Perspex.Diagnostics { PerspexXamlLoader.Load(this); } + + private void RootPointerMoved(object sender, PointerEventArgs e) + { + var modifiers = InputModifiers.Control | InputModifiers.Shift; + + if ((e.InputModifiers & modifiers) == modifiers) + { + var vm = (DevToolsViewModel)DataContext; + vm.SelectControl((IControl)e.Source); + } + } } } diff --git a/src/Perspex.Diagnostics/ViewModels/DevToolsViewModel.cs b/src/Perspex.Diagnostics/ViewModels/DevToolsViewModel.cs index ef9dc5a371..475579fdb5 100644 --- a/src/Perspex.Diagnostics/ViewModels/DevToolsViewModel.cs +++ b/src/Perspex.Diagnostics/ViewModels/DevToolsViewModel.cs @@ -69,5 +69,15 @@ namespace Perspex.Diagnostics.ViewModels public string FocusedControl => _focusedControl.Value; public string PointerOverElement => _pointerOverElement.Value; + + public void SelectControl(IControl control) + { + var tree = Content as TreePageViewModel; + + if (tree != null) + { + tree.SelectControl(control); + } + } } } diff --git a/src/Perspex.Diagnostics/ViewModels/LogicalTreeNode.cs b/src/Perspex.Diagnostics/ViewModels/LogicalTreeNode.cs index 0d15719128..bef186b246 100644 --- a/src/Perspex.Diagnostics/ViewModels/LogicalTreeNode.cs +++ b/src/Perspex.Diagnostics/ViewModels/LogicalTreeNode.cs @@ -9,16 +9,16 @@ namespace Perspex.Diagnostics.ViewModels { internal class LogicalTreeNode : TreeNode { - public LogicalTreeNode(ILogical logical) - : base((Control)logical) + public LogicalTreeNode(ILogical logical, TreeNode parent) + : base((Control)logical, parent) { - Children = logical.LogicalChildren.CreateDerivedCollection(x => new LogicalTreeNode(x)); + Children = logical.LogicalChildren.CreateDerivedCollection(x => new LogicalTreeNode(x, this)); } public static LogicalTreeNode[] Create(object control) { var logical = control as ILogical; - return logical != null ? new[] { new LogicalTreeNode(logical) } : null; + return logical != null ? new[] { new LogicalTreeNode(logical, null) } : null; } } } diff --git a/src/Perspex.Diagnostics/ViewModels/TreeNode.cs b/src/Perspex.Diagnostics/ViewModels/TreeNode.cs index 9c46f5f344..62044d2a28 100644 --- a/src/Perspex.Diagnostics/ViewModels/TreeNode.cs +++ b/src/Perspex.Diagnostics/ViewModels/TreeNode.cs @@ -13,11 +13,12 @@ namespace Perspex.Diagnostics.ViewModels internal class TreeNode : ReactiveObject { private string _classes; - private bool _isExpanded = true; + private bool _isExpanded; - public TreeNode(Control control) + public TreeNode(Control control, TreeNode parent) { Control = control; + Parent = parent; Type = control.GetType().Name; var classesChanged = Observable.FromEventPattern< @@ -53,19 +54,23 @@ namespace Perspex.Diagnostics.ViewModels private set { this.RaiseAndSetIfChanged(ref _classes, value); } } + public Control Control + { + get; + } + public bool IsExpanded { get { return _isExpanded; } - private set { this.RaiseAndSetIfChanged(ref _isExpanded, value); } + set { this.RaiseAndSetIfChanged(ref _isExpanded, value); } } - public string Type + public TreeNode Parent { get; - private set; } - public Control Control + public string Type { get; private set; diff --git a/src/Perspex.Diagnostics/ViewModels/TreePageViewModel.cs b/src/Perspex.Diagnostics/ViewModels/TreePageViewModel.cs index 90e1b49492..346969abdc 100644 --- a/src/Perspex.Diagnostics/ViewModels/TreePageViewModel.cs +++ b/src/Perspex.Diagnostics/ViewModels/TreePageViewModel.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System.Reactive.Linq; +using Perspex.Controls; +using Perspex.VisualTree; using ReactiveUI; namespace Perspex.Diagnostics.ViewModels @@ -29,5 +31,72 @@ namespace Perspex.Diagnostics.ViewModels } public ControlDetailsViewModel Details => _details.Value; + + public TreeNode FindNode(IControl control) + { + foreach (var node in Nodes) + { + var result = FindNode(node, control); + + if (result != null) + { + return result; + } + } + + return null; + } + + public void SelectControl(IControl control) + { + var node = default(TreeNode); + + while (node == null && control != null) + { + node = FindNode(control); + + if (node == null) + { + control = control.GetVisualParent(); + } + } + + if (node != null) + { + SelectedNode = node; + ExpandNode(node.Parent); + } + } + + private void ExpandNode(TreeNode node) + { + if (node != null) + { + node.IsExpanded = true; + ExpandNode(node.Parent); + } + } + + private TreeNode FindNode(TreeNode node, IControl control) + { + if (node.Control == control) + { + return node; + } + else + { + foreach (var child in node.Children) + { + var result = FindNode(child, control); + + if (result != null) + { + return result; + } + } + } + + return null; + } } } diff --git a/src/Perspex.Diagnostics/ViewModels/VisualTreeNode.cs b/src/Perspex.Diagnostics/ViewModels/VisualTreeNode.cs index 64064df20a..f92a51439a 100644 --- a/src/Perspex.Diagnostics/ViewModels/VisualTreeNode.cs +++ b/src/Perspex.Diagnostics/ViewModels/VisualTreeNode.cs @@ -9,18 +9,18 @@ namespace Perspex.Diagnostics.ViewModels { internal class VisualTreeNode : TreeNode { - public VisualTreeNode(IVisual visual) - : base((Control)visual) + public VisualTreeNode(IVisual visual, TreeNode parent) + : base((Control)visual, parent) { var host = visual as IVisualTreeHost; if (host?.Root == null) { - Children = visual.VisualChildren.CreateDerivedCollection(x => new VisualTreeNode(x)); + Children = visual.VisualChildren.CreateDerivedCollection(x => new VisualTreeNode(x, this)); } else { - Children = new ReactiveList(new[] { new VisualTreeNode(host.Root) }); + Children = new ReactiveList(new[] { new VisualTreeNode(host.Root, this) }); } if (Control != null) @@ -34,7 +34,7 @@ namespace Perspex.Diagnostics.ViewModels public static VisualTreeNode[] Create(object control) { var visual = control as IVisual; - return visual != null ? new[] { new VisualTreeNode(visual) } : null; + return visual != null ? new[] { new VisualTreeNode(visual, null) } : null; } } } diff --git a/src/Perspex.Diagnostics/Views/TreePageView.paml b/src/Perspex.Diagnostics/Views/TreePageView.paml index 4914d1e3dc..ba13d4e263 100644 --- a/src/Perspex.Diagnostics/Views/TreePageView.paml +++ b/src/Perspex.Diagnostics/Views/TreePageView.paml @@ -11,11 +11,11 @@ - +