From a3762291c1c2a58f2d2047e17cbdaad41cfb995c Mon Sep 17 00:00:00 2001 From: workgroupengineering Date: Fri, 19 Apr 2024 01:22:24 +0200 Subject: [PATCH] feat(DevTools): Add Avalonia_DevTools_Selectors Clipoard format for quicks IDE recongnize. (#14603) --- .../Diagnostics/Constants.cs | 15 ++++++++ .../ViewModels/TreePageViewModel.cs | 22 ++++++------ .../Diagnostics/Views/TreePageView.xaml.cs | 35 +++++++++++++++++-- 3 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 src/Avalonia.Diagnostics/Diagnostics/Constants.cs diff --git a/src/Avalonia.Diagnostics/Diagnostics/Constants.cs b/src/Avalonia.Diagnostics/Diagnostics/Constants.cs new file mode 100644 index 00000000000..1686ddf8cf0 --- /dev/null +++ b/src/Avalonia.Diagnostics/Diagnostics/Constants.cs @@ -0,0 +1,15 @@ +namespace Avalonia.Diagnostics; + +internal static class Constants +{ + /// + /// DevTools Clipboard data format + /// + static public class DataFormats + { + /// + /// Clipboard data format for the selector. It is added for quick format recognition in IDEs + /// + public const string Avalonia_DevTools_Selector = nameof(Avalonia_DevTools_Selector); + } +} diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs index f6fe121f283..e56b0606d6e 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs @@ -25,7 +25,7 @@ public TreePageViewModel(MainViewModel mainView, TreeNode[] nodes, ISet } public event EventHandler? ClipboardCopyRequested; - + public MainViewModel MainView { get; } public FilterViewModel PropertiesFilter { get; } @@ -117,11 +117,11 @@ public void CopySelector() if (currentVisual is not null) { var selector = GetVisualSelector(currentVisual); - + ClipboardCopyRequested?.Invoke(this, selector); } } - + public void CopySelectorFromTemplateParent() { var parts = new List(); @@ -130,7 +130,7 @@ public void CopySelectorFromTemplateParent() while (currentVisual is not null) { parts.Add(GetVisualSelector(currentVisual)); - + currentVisual = currentVisual.TemplatedParent as Visual; } @@ -148,7 +148,7 @@ public void ExpandRecursively() if (SelectedNode is { } selectedNode) { ExpandNode(selectedNode); - + var stack = new Stack(); stack.Push(selectedNode); @@ -192,8 +192,8 @@ public void BringIntoView() { (SelectedNode?.Visual as Control)?.BringIntoView(); } - - + + public void Focus() { (SelectedNode?.Visual as Control)?.Focus(); @@ -205,10 +205,10 @@ private static string GetVisualSelector(Visual visual) var classes = string.Concat(visual.Classes .Where(c => !c.StartsWith(":")) .Select(c => '.' + c)); - var typeName = StyledElement.GetStyleKey(visual); - - return $"{typeName}{name}{classes}"; - } + var pseudo = string.Concat(visual.Classes.Where(c => c[0] == ':').Select(c => c)); + var type = StyledElement.GetStyleKey(visual); + return $$"""{{{type.Assembly.FullName}}}{{type.Namespace}}|{{type.Name}}{{name}}{{classes}}{{pseudo}}"""; + } private void ExpandNode(TreeNode? node) { diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml.cs index 69dc375edef..7597cf9ef49 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml.cs @@ -75,9 +75,40 @@ private void InitializeComponent() AvaloniaXamlLoader.Load(this); } - private void OnClipboardCopyRequested(object? sender, string e) + private void OnClipboardCopyRequested(object? sender, string selector) { - TopLevel.GetTopLevel(this)?.Clipboard?.SetTextAsync(e); + if (TopLevel.GetTopLevel(this)?.Clipboard is { } clipboard) + { + var @do = new DataObject(); + var text = ToText(selector); + @do.Set(DataFormats.Text, text); + @do.Set(Constants.DataFormats.Avalonia_DevTools_Selector, selector); + clipboard.SetDataObjectAsync(@do); + } + } + + private static string ToText(string text) + { + var sb = new System.Text.StringBuilder(); + var bufferStartIndex = -1; + for (var ic = 0; ic < text.Length; ic++) + { + var c = text[ic]; + switch (c) + { + case '{': + bufferStartIndex = sb.Length; + break; + case '}' when bufferStartIndex > -1: + sb.Remove(bufferStartIndex, sb.Length - bufferStartIndex); + bufferStartIndex = sb.Length; + break; + default: + sb.Append(c); + break; + } + } + return sb.ToString(); } } }