2
0
CPKreuz 2 жил өмнө
parent
commit
ce1a019546

+ 14 - 0
src/PixiEditor/Models/Commands/Attributes/Commands/FilterAttribute.cs

@@ -0,0 +1,14 @@
+namespace PixiEditor.Models.Commands.Attributes.Commands;
+
+internal partial class Command
+{
+    public class FilterAttribute : CommandAttribute
+    {
+        public string SearchTerm { get; }
+        
+        public FilterAttribute(string internalName, string displayName, string searchTerm) : base(internalName, displayName, string.Empty)
+        {
+            SearchTerm = searchTerm;
+        }
+    }
+}

+ 22 - 1
src/PixiEditor/Models/Commands/CommandController.cs

@@ -24,6 +24,8 @@ internal class CommandController
 
     public List<CommandGroup> CommandGroups { get; }
 
+    public OneToManyDictionary<string, Command> FilterCommands { get; }
+
     public Dictionary<string, CanExecuteEvaluator> CanExecuteEvaluators { get; }
 
     public Dictionary<string, IconEvaluator> IconEvaluators { get; }
@@ -39,6 +41,7 @@ internal class CommandController
 
         shortcutFile = new(ShortcutsPath, this);
 
+        FilterCommands = new();
         Commands = new();
         CommandGroups = new();
         CanExecuteEvaluators = new();
@@ -211,11 +214,27 @@ internal class CommandController
                                 Parameter = basic.Parameter,
                             });
                     }
+                    else if (attribute is CommandAttribute.FilterAttribute menu)
+                    {
+                        foreach (var menuCommand in commandAttrs.Where(x => x is not CommandAttribute.FilterAttribute))
+                        {
+                            FilterCommands.Add(menu.SearchTerm, Commands[menuCommand.InternalName]);
+                        }
+                        
+                        Commands.Add(new Command.BasicCommand(_ => ViewModelMain.Current.SearchSubViewModel.OpenSearchWindow($":{menu.SearchTerm}:"), CanExecuteEvaluator.AlwaysTrue)
+                        {
+                            InternalName = menu.InternalName,
+                            DisplayName = menu.DisplayName,
+                            Description = string.Empty,
+                            DefaultShortcut = menu.GetShortcut(),
+                            Shortcut = GetShortcut(name, attribute.GetShortcut(), template)
+                        });
+                    }
                 }
             }
         }
         
-        void AddCommand<TAttr, TCommand>(MethodInfo method, object instance, TAttr attribute,
+        TCommand AddCommand<TAttr, TCommand>(MethodInfo method, object instance, TAttr attribute,
             Func<bool, string, Action<object>, CanExecuteEvaluator, IconEvaluator, TCommand> commandFactory)
             where TAttr : CommandAttribute.CommandAttribute
             where TCommand : Command
@@ -264,6 +283,8 @@ internal class CommandController
 
             Commands.Add(command);
             AddCommandToCommandsCollection(command, commandGroupsData, commands);
+
+            return command;
         }
     }
 

+ 15 - 0
src/PixiEditor/ViewModels/SubViewModels/Main/SearchViewModel.cs

@@ -7,6 +7,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main;
 internal class SearchViewModel : SubViewModel<ViewModelMain>
 {
     private bool searchWindowOpen;
+    private bool selectAll;
     private string searchTerm;
 
     public bool SearchWindowOpen
@@ -21,6 +22,12 @@ internal class SearchViewModel : SubViewModel<ViewModelMain>
         set => SetProperty(ref searchTerm, value);
     }
 
+    public bool SelectAll
+    {
+        get => selectAll;
+        set => SetProperty(ref selectAll, value);
+    }
+
     public SearchViewModel(ViewModelMain owner) : base(owner)
     { }
 
@@ -30,10 +37,18 @@ internal class SearchViewModel : SubViewModel<ViewModelMain>
     [Command.Basic("PixiEditor.Search.Toggle", "", "Command Search", "Open the command search window", Key = Key.K, Modifiers = ModifierKeys.Control, CanExecute = "PixiEditor.Search.CanOpenSearchWindow")]
     public void ToggleSearchWindow(string searchTerm)
     {
+        SelectAll = true;
         SearchWindowOpen = !SearchWindowOpen;
         if (SearchWindowOpen)
         {
             SearchTerm = searchTerm;
         }
     }
+
+    public void OpenSearchWindow(string searchTerm, bool selectAll = true)
+    {
+        SelectAll = selectAll;
+        SearchWindowOpen = true;
+        SearchTerm = searchTerm;
+    }
 }

+ 2 - 1
src/PixiEditor/ViewModels/SubViewModels/Main/SelectionViewModel.cs

@@ -53,10 +53,11 @@ internal class SelectionViewModel : SubViewModel<ViewModelMain>
         Owner.DocumentManagerSubViewModel.ActiveDocument?.Operations.NudgeSelectedObject(distance);
     }
 
-    [Command.Basic("PixiEditor.Selection.NewToMask", SelectionMode.New, "Selection to mask", "Selection to new mask")]
+    [Command.Basic("PixiEditor.Selection.NewToMask", SelectionMode.New, "New mask from selection", "Selection to new mask")]
     [Command.Basic("PixiEditor.Selection.AddToMask", SelectionMode.Add, "Add selection to mask", "Add selection to mask")]
     [Command.Basic("PixiEditor.Selection.SubtractFromMask", SelectionMode.Subtract, "Subtract selection from mask", "Subtract selection from mask")]
     [Command.Basic("PixiEditor.Selection.IntersectSelectionMask", SelectionMode.Intersect, "Intersect selection with mask", "Intersect selection with mask")]
+    [Command.Filter("PixiEditor.Selection.ToMaskMenu", "Selection to mask", "Selection to mask", Key = Key.M, Modifiers = ModifierKeys.Control)]
     public void SelectionToMask(SelectionMode mode)
     {
         Owner.DocumentManagerSubViewModel.ActiveDocument?.Operations.SelectionToMask(mode);

+ 1 - 1
src/PixiEditor/Views/UserControls/CommandSearch/CommandSearchControl.xaml

@@ -24,7 +24,7 @@
                  Padding="5"
                  x:Name="textBox">
             <i:Interaction.Behaviors>
-                <behaves:TextBoxFocusBehavior SelectOnMouseClick="True" />
+                <behaves:TextBoxFocusBehavior SelectOnMouseClick="{Binding SelectAll, ElementName=uc, Mode=OneWay}" />
                 <behaves:GlobalShortcutFocusBehavior />
             </i:Interaction.Behaviors>
             <TextBox.Style>

+ 14 - 0
src/PixiEditor/Views/UserControls/CommandSearch/CommandSearchControl.xaml.cs

@@ -22,6 +22,15 @@ internal partial class CommandSearchControl : UserControl, INotifyPropertyChange
         get => (string)GetValue(SearchTermProperty);
         set => SetValue(SearchTermProperty, value);
     }
+    
+    public static readonly DependencyProperty SelectAllProperty =
+        DependencyProperty.Register(nameof(SelectAll), typeof(bool), typeof(CommandSearchControl));
+
+    public bool SelectAll
+    {
+        get => (bool)GetValue(SelectAllProperty);
+        set => SetValue(SelectAllProperty, value);
+    }
 
     private string warnings = "";
     public string Warnings
@@ -89,6 +98,11 @@ internal partial class CommandSearchControl : UserControl, INotifyPropertyChange
                     textBox.Focus();
                     UpdateSearchResults();
                     Mouse.Capture(this, CaptureMode.SubTree);
+
+                    if (!SelectAll)
+                    {
+                        textBox.CaretIndex = SearchTerm?.Length ?? 0;
+                    }
                 });
             }
         };

+ 30 - 0
src/PixiEditor/Views/UserControls/CommandSearch/CommandSearchControlHelper.cs

@@ -31,6 +31,36 @@ internal static class CommandSearchControlHelper
 
         var controller = CommandController.Current;
 
+        if (query.StartsWith(':') && query.Length > 1)
+        {
+            string searchTerm = query[1..].Replace(" ", "");
+            int index = searchTerm.IndexOf(':');
+
+            string menu;
+            string additional;
+            
+            if (index > 0)
+            {
+                menu = searchTerm[..index];
+                additional = searchTerm[(index + 1)..];
+            }
+            else
+            {
+                menu = searchTerm;
+                additional = string.Empty;
+            }
+
+            var menuCommands = controller.FilterCommands
+                .Where(x => x.Key.Replace(" ", "").Contains(menu, StringComparison.OrdinalIgnoreCase))
+                .SelectMany(x => x.Value);
+
+            newResults.AddRange(menuCommands
+                .Where(x => index == -1 || x.DisplayName.Replace(" ", "").Contains(additional, StringComparison.OrdinalIgnoreCase))
+                .Select(command => new CommandSearchResult(command) { SearchTerm = searchTerm }));
+
+            return (newResults, warnings);
+        }
+        
         // add matching colors
         MaybeParseColor(query).Switch(
             color =>