Jelajahi Sumber

Command Search WIP

CPKreuz 3 tahun lalu
induk
melakukan
2055d4e58d
48 mengubah file dengan 987 tambahan dan 372 penghapusan
  1. 33 0
      PixiEditor/Helpers/Behaviours/TextBlockExtensions.cs
  2. 8 11
      PixiEditor/Helpers/Converters/FileExtensionToColorConverter.cs
  3. TEMPAT SAMPAH
      PixiEditor/Images/Commands/PixiEditor/Clipboard/Copy.png
  4. TEMPAT SAMPAH
      PixiEditor/Images/Commands/PixiEditor/Clipboard/Cut.png
  5. TEMPAT SAMPAH
      PixiEditor/Images/Commands/PixiEditor/Clipboard/Paste.png
  6. TEMPAT SAMPAH
      PixiEditor/Images/Commands/PixiEditor/Colors/Swap.png
  7. TEMPAT SAMPAH
      PixiEditor/Images/Commands/PixiEditor/Document/CenterContent.png
  8. TEMPAT SAMPAH
      PixiEditor/Images/Commands/PixiEditor/Document/ResizeCanvas.png
  9. TEMPAT SAMPAH
      PixiEditor/Images/Commands/PixiEditor/Document/ResizeDocument.png
  10. 4 4
      PixiEditor/Models/Commands/Attributes/Commands/BasicAttribute.cs
  11. 16 0
      PixiEditor/Models/Commands/Attributes/Commands/CommandAttribute.cs
  12. 12 0
      PixiEditor/Models/Commands/Attributes/Commands/ToolAttribute.cs
  13. 12 0
      PixiEditor/Models/Commands/Attributes/Evaluators/IconAttribute.cs
  14. 78 25
      PixiEditor/Models/Commands/CommandController.cs
  15. 8 4
      PixiEditor/Models/Commands/CommandMethods.cs
  16. 3 1
      PixiEditor/Models/Commands/Commands/BasicCommand.cs
  17. 11 1
      PixiEditor/Models/Commands/Commands/Command.cs
  18. 16 0
      PixiEditor/Models/Commands/Commands/ToolCommand.cs
  19. 15 0
      PixiEditor/Models/Commands/Evaluators/CanExecuteEvaluator.cs
  20. 3 1
      PixiEditor/Models/Commands/Evaluators/Evaluator.cs
  21. 75 0
      PixiEditor/Models/Commands/Evaluators/IconEvaluator.cs
  22. 22 0
      PixiEditor/Models/Commands/Search/CommandSearchResult.cs
  23. 37 0
      PixiEditor/Models/Commands/Search/FileSearchResult.cs
  24. 60 0
      PixiEditor/Models/Commands/Search/SearchResult.cs
  25. 13 17
      PixiEditor/Models/Commands/XAML/Command.cs
  26. 5 5
      PixiEditor/Models/Commands/XAML/ShortcutBinding.cs
  27. 0 1
      PixiEditor/Models/Tools/Tool.cs
  28. 3 2
      PixiEditor/Models/Tools/Tools/BrightnessTool.cs
  29. 3 0
      PixiEditor/Models/Tools/Tools/CircleTool.cs
  30. 3 2
      PixiEditor/Models/Tools/Tools/ColorPickerTool.cs
  31. 4 2
      PixiEditor/Models/Tools/Tools/EraserTool.cs
  32. 3 1
      PixiEditor/Models/Tools/Tools/FloodFillTool.cs
  33. 3 2
      PixiEditor/Models/Tools/Tools/LineTool.cs
  34. 3 1
      PixiEditor/Models/Tools/Tools/MagicWandTool.cs
  35. 2 2
      PixiEditor/Models/Tools/Tools/MoveTool.cs
  36. 4 2
      PixiEditor/Models/Tools/Tools/MoveViewportTool.cs
  37. 3 4
      PixiEditor/Models/Tools/Tools/PenTool.cs
  38. 3 2
      PixiEditor/Models/Tools/Tools/RectangleTool.cs
  39. 4 3
      PixiEditor/Models/Tools/Tools/SelectTool.cs
  40. 4 3
      PixiEditor/Models/Tools/Tools/ZoomTool.cs
  41. 14 0
      PixiEditor/PixiEditor.csproj
  42. 2 1
      PixiEditor/Styles/ThemeStyle.xaml
  43. 84 0
      PixiEditor/ViewModels/CommandSearchViewModel.cs
  44. 1 1
      PixiEditor/ViewModels/SubViewModels/Main/DocumentViewModel.cs
  45. 1 1
      PixiEditor/ViewModels/SubViewModels/Main/LayersViewModel.cs
  46. 276 273
      PixiEditor/Views/MainWindow.xaml
  47. 110 0
      PixiEditor/Views/UserControls/CommandSearchControl.xaml
  48. 26 0
      PixiEditor/Views/UserControls/CommandSearchControl.xaml.cs

+ 33 - 0
PixiEditor/Helpers/Behaviours/TextBlockExtensions.cs

@@ -0,0 +1,33 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+
+namespace PixiEditor.Helpers.Behaviours
+{
+    public static class TextBlockExtensions
+    {
+        public static IEnumerable<Inline> GetBindableInlines(DependencyObject obj)
+        {
+            return (IEnumerable<Inline>)obj.GetValue(BindableInlinesProperty);
+        }
+
+        public static void SetBindableInlines(DependencyObject obj, IEnumerable<Inline> value)
+        {
+            obj.SetValue(BindableInlinesProperty, value);
+        }
+
+        public static readonly DependencyProperty BindableInlinesProperty =
+            DependencyProperty.RegisterAttached("BindableInlines", typeof(IEnumerable<Inline>), typeof(TextBlockExtensions), new PropertyMetadata(null, OnBindableInlinesChanged));
+
+        private static void OnBindableInlinesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            if (d is not TextBlock target)
+            {
+                return;
+            }
+
+            target.Inlines.Clear();
+            target.Inlines.AddRange((System.Collections.IEnumerable)e.NewValue);
+        }
+    }
+}

+ 8 - 11
PixiEditor/Helpers/Converters/FileExtensionToColorConverter.cs

@@ -1,11 +1,7 @@
-using PixiEditor.Models;
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Drawing.Imaging;
+using PixiEditor.Models.Enums;
 using System.Globalization;
+using System.IO;
 using System.Windows.Media;
-using PixiEditor.Models.Enums;
 
 namespace PixiEditor.Helpers.Converters
 {
@@ -29,12 +25,13 @@ namespace PixiEditor.Helpers.Converters
         {
             SupportedFilesHelper.GetFileTypeDialogData(format).Extensions.ForEach(i => extensionsToBrushes[i] = brush);
         }
-        
-        public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            string extension = (string)value;
 
-            return extensionsToBrushes.ContainsKey(extension) ? extensionsToBrushes[extension] : UnknownBrush;
+        public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
+            GetBrush((string)value);
+
+        public static Brush GetBrush(string path)
+        {
+            return extensionsToBrushes.GetValueOrDefault(Path.GetExtension(path).ToLower(), UnknownBrush);
         }
 
         private static SolidColorBrush ColorBrush(byte r, byte g, byte b)

TEMPAT SAMPAH
PixiEditor/Images/Commands/PixiEditor/Clipboard/Copy.png


TEMPAT SAMPAH
PixiEditor/Images/Commands/PixiEditor/Clipboard/Cut.png


TEMPAT SAMPAH
PixiEditor/Images/Commands/PixiEditor/Clipboard/Paste.png


TEMPAT SAMPAH
PixiEditor/Images/Commands/PixiEditor/Colors/Swap.png


TEMPAT SAMPAH
PixiEditor/Images/Commands/PixiEditor/Document/CenterContent.png


TEMPAT SAMPAH
PixiEditor/Images/Commands/PixiEditor/Document/ResizeCanvas.png


TEMPAT SAMPAH
PixiEditor/Images/Commands/PixiEditor/Document/ResizeDocument.png


+ 4 - 4
PixiEditor/Models/Commands/Attributes/Commands/BasicAttribute.cs

@@ -4,6 +4,9 @@ public partial class Command
 {
     public class BasicAttribute : CommandAttribute
     {
+        /// <summary>
+        /// Gets or sets the parameter that will be passed to the first argument of the method
+        /// </summary>
         public object Parameter { get; set; }
 
         /// <summary>
@@ -12,8 +15,6 @@ public partial class Command
         /// <param name="name">The name of the command</param>
         /// <param name="display">A short description which is displayed in the the top menu, e.g. "Save as..."</param>
         /// <param name="description">A description which is displayed in the search bar, e.g. "Save image as new". Leave empty to hide it from the search bar</param>
-        /// <param name="key">The default shortcut key of the command</param>
-        /// <param name="modifiers">The default shortcut modifier keys of the command</param>
         public BasicAttribute(string name, string display, string description)
             : this(name, null, display, description)
         {
@@ -23,10 +24,9 @@ public partial class Command
         /// Create's a basic command which uses <paramref name="parameter"/> as the parameter
         /// </summary>
         /// <param name="name">The name of the command</param>
+        /// <param name="parameter">The parameter that will be passed to the first argument of the method</param>
         /// <param name="display">A short description which is displayed in the the top menu, e.g. "Save as..."</param>
         /// <param name="description">A description which is displayed in the search bar, e.g. "Save image as new". Leave empty to hide it from the search bar</param>
-        /// <param name="key">The default shortcut key of the command</param>
-        /// <param name="modifiers">The default shortcut modifier keys of the command</param>
         public BasicAttribute(string name, object parameter, string display, string description)
             : base(name, display, description)
         {

+ 16 - 0
PixiEditor/Models/Commands/Attributes/Commands/CommandAttribute.cs

@@ -16,10 +16,26 @@ public partial class Command
 
         public string CanExecute { get; set; }
 
+        /// <summary>
+        /// Gets or sets the default shortcut key for this command
+        /// </summary>
         public Key Key { get; set; }
 
+        /// <summary>
+        /// Gets or sets the default shortcut modfiers keys for this command
+        /// </summary>
         public ModifierKeys Modifiers { get; set; }
 
+        /// <summary>
+        /// Gets or sets the name of the icon evaluator for this command
+        /// </summary>
+        public string IconEvaluator { get; set; }
+
+        /// <summary>
+        /// Gets or sets path to the icon. Must be bitmap image
+        /// </summary>
+        public string Icon { get; set; }
+
         protected CommandAttribute(string name, string display, string description)
         {
             Name = name;

+ 12 - 0
PixiEditor/Models/Commands/Attributes/Commands/ToolAttribute.cs

@@ -0,0 +1,12 @@
+namespace PixiEditor.Models.Commands.Attributes;
+
+public partial class Command
+{
+    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+    public class ToolAttribute : CommandAttribute
+    {
+        public ToolAttribute() : base(null, null, null)
+        {
+        }
+    }
+}

+ 12 - 0
PixiEditor/Models/Commands/Attributes/Evaluators/IconAttribute.cs

@@ -0,0 +1,12 @@
+namespace PixiEditor.Models.Commands.Attributes;
+
+public partial class Evaluator
+{
+    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = true)]
+    public class IconAttribute : EvaluatorAttribute
+    {
+        public IconAttribute(string name)
+            : base(name)
+        { }
+    }
+}

+ 78 - 25
PixiEditor/Models/Commands/CommandController.cs

@@ -1,6 +1,9 @@
-using PixiEditor.Models.Commands.Attributes;
+using Microsoft.Extensions.DependencyInjection;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Commands.Evaluators;
+using PixiEditor.Models.Tools;
 using System.Reflection;
+using System.Windows.Media;
 using CommandAttribute = PixiEditor.Models.Commands.Attributes.Command;
 
 namespace PixiEditor.Models.Commands
@@ -15,15 +18,18 @@ namespace PixiEditor.Models.Commands
 
         public Dictionary<string, CanExecuteEvaluator> CanExecuteEvaluators { get; set; }
 
+        public Dictionary<string, IconEvaluator> IconEvaluators { get; set; }
+
         public CommandController(IServiceProvider services)
         {
+            Current ??= this;
+
             Commands = new();
             FactoryEvaluators = new();
             CanExecuteEvaluators = new();
+            IconEvaluators = new();
 
             Init(services);
-
-            Current ??= this;
         }
 
         public void Init(IServiceProvider services)
@@ -54,12 +60,23 @@ namespace PixiEditor.Models.Commands
                         {
                             AddEvaluator<Evaluator.FactoryAttribute, FactoryEvaluator, object>(method, instanceType, factory, FactoryEvaluators);
                         }
+                        else if (attribute is Evaluator.IconAttribute icon)
+                        {
+                            AddEvaluator<Evaluator.IconAttribute, IconEvaluator, ImageSource>(method, instanceType, icon, IconEvaluators);
+                        }
                     }
                 }
 
+            }
+
+            foreach (var type in types)
+            {
+                object instanceType = null;
+                var methods = type.GetMethods();
+
                 foreach (var method in methods)
                 {
-                    var commandAttrs = method.GetCustomAttributes<CommandAttribute.BasicAttribute>();
+                    var commandAttrs = method.GetCustomAttributes<CommandAttribute.CommandAttribute>();
 
                     if (instanceType is null && commandAttrs.Any())
                     {
@@ -68,16 +85,42 @@ namespace PixiEditor.Models.Commands
 
                     foreach (var attribute in commandAttrs)
                     {
-                        AddCommand(method, instanceType, attribute, (isDebug, name, x, xCan) => new Command.BasicCommand
+                        if (attribute is CommandAttribute.BasicAttribute basic)
                         {
-                            Name = name,
-                            IsDebug = isDebug,
-                            Display = attribute.Display,
-                            Description = attribute.Description,
-                            Methods = new(x, xCan),
-                            DefaultShortcut = attribute.GetShortcut(),
-                            Parameter = attribute.Parameter,
-                            Shortcut = attribute.GetShortcut(),
+                            AddCommand(method, instanceType, attribute, (isDebug, name, x, xCan, xIcon) => new Command.BasicCommand(x, xCan)
+                            {
+                                Name = name,
+                                IsDebug = isDebug,
+                                Display = attribute.Display,
+                                Description = attribute.Description,
+                                IconPath = attribute.Icon,
+                                IconEvaluator = xIcon,
+                                DefaultShortcut = attribute.GetShortcut(),
+                                Parameter = basic.Parameter,
+                                Shortcut = attribute.GetShortcut(),
+                            });
+                        }
+                    }
+                }
+
+                if (type.IsAssignableTo(typeof(Tool)))
+                {
+                    var toolAttr = type.GetCustomAttribute<CommandAttribute.ToolAttribute>();
+
+                    if (toolAttr != null)
+                    {
+                        var tool = services.GetServices<Tool>().First(x => x.GetType() == type);
+
+                        Commands.Add(new Command.ToolCommand()
+                        {
+                            Name = $"PixiEditor.Tools.Select.{type.Name}",
+                            Display = $"Select {tool.DisplayName} Tool",
+                            Description = $"Select {tool.DisplayName} Tool",
+                            IconPath = $"@{tool.ImagePath}",
+                            IconEvaluator = IconEvaluator.Default,
+                            DefaultShortcut = toolAttr.GetShortcut(),
+                            ToolType = type,
+                            Shortcut = toolAttr.GetShortcut(),
                         });
                     }
                 }
@@ -122,29 +165,33 @@ namespace PixiEditor.Models.Commands
                 evaluators.Add(evaluator.Name, evaluator);
             }
 
-            void AddCommand<TAttr, TCommand>(MethodInfo method, object instance, TAttr attribute, Func<bool, string, Action<object>, Predicate<object>, TCommand> commandFactory)
+            void 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
-            {if (method.GetParameters().Length > 1)
-                {
-                    throw new Exception($"Too many parameters for the CanExecute evaluator '{attribute.Name}' at {method.ReflectedType.FullName}.{method.Name}");
-                }
-                else if (!method.IsStatic && instance is null)
+            {
+                if (method != null)
                 {
-                    throw new Exception($"No type instance for the CanExecute evaluator '{attribute.Name}' at {method.ReflectedType.FullName}.{method.Name} found");
+                    if (method.GetParameters().Length > 1)
+                    {
+                        throw new Exception($"Too many parameters for the CanExecute evaluator '{attribute.Name}' at {method.ReflectedType.FullName}.{method.Name}");
+                    }
+                    else if (!method.IsStatic && instance is null)
+                    {
+                        throw new Exception($"No type instance for the CanExecute evaluator '{attribute.Name}' at {method.ReflectedType.FullName}.{method.Name} found");
+                    }
                 }
 
-                var parameters = method.GetParameters();
+                var parameters = method?.GetParameters();
 
                 Action<object> action;
 
-                if (parameters.Length == 1)
+                if (parameters == null || parameters.Length != 1)
                 {
-                    action = x => method.Invoke(instance, new[] { x });
+                    action = x => method.Invoke(instance, null);
                 }
                 else
                 {
-                    action = x => method.Invoke(instance, null);
+                    action = x => method.Invoke(instance, new[] { x });
                 }
 
                 string name = attribute.Name;
@@ -155,7 +202,13 @@ namespace PixiEditor.Models.Commands
                     name = name["#DEBUG#".Length..];
                 }
 
-                Commands.Add(commandFactory(isDebug, name, action, x => attribute.CanExecute == null || CanExecuteEvaluators[attribute.CanExecute].Evaluate(x)));
+                Commands.Add(
+                    commandFactory(
+                        isDebug,
+                        name,
+                        action,
+                        attribute.CanExecute != null ? CanExecuteEvaluators[attribute.CanExecute] : CanExecuteEvaluator.AlwaysTrue,
+                        attribute.IconEvaluator != null ? IconEvaluators[attribute.IconEvaluator] : IconEvaluator.Default));
             }
         }
     }

+ 8 - 4
PixiEditor/Models/Commands/CommandMethods.cs

@@ -1,14 +1,18 @@
-namespace PixiEditor.Models.Commands;
+using PixiEditor.Models.Commands.Evaluators;
+
+namespace PixiEditor.Models.Commands;
 
 public class CommandMethods
 {
+    private readonly Command _command;
     private readonly Action<object> _execute;
-    private readonly Predicate<object> _canExecute;
+    private readonly CanExecuteEvaluator _canExecute;
 
-    public CommandMethods(Action<object> execute, Predicate<object> canExecute)
+    public CommandMethods(Command command, Action<object> execute, CanExecuteEvaluator canExecute)
     {
         _execute = execute;
         _canExecute = canExecute;
+        _command = command;
     }
 
     public void Execute(object parameter)
@@ -19,5 +23,5 @@ public class CommandMethods
         }
     }
 
-    public bool CanExecute(object parameter) => _canExecute(parameter);
+    public bool CanExecute(object parameter) => _canExecute.EvaluateEvaluator(_command, parameter);
 }

+ 3 - 1
PixiEditor/Models/Commands/Commands/BasicCommand.cs

@@ -1,4 +1,4 @@
-using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.Commands.Evaluators;
 
 namespace PixiEditor.Models.Commands
 {
@@ -9,6 +9,8 @@ namespace PixiEditor.Models.Commands
             public object Parameter { get; init; }
 
             protected override object GetParameter() => Parameter;
+
+            public BasicCommand(Action<object> onExecute, CanExecuteEvaluator canExecute) : base(onExecute, canExecute) { }
         }
     }
 }

+ 11 - 1
PixiEditor/Models/Commands/Commands/Command.cs

@@ -1,7 +1,8 @@
 using PixiEditor.Helpers;
+using PixiEditor.Models.Commands.Evaluators;
 using PixiEditor.Models.DataHolders;
 using System.Diagnostics;
-using System.Windows.Input;
+using System.Windows.Media;
 
 namespace PixiEditor.Models.Commands
 {
@@ -14,6 +15,10 @@ namespace PixiEditor.Models.Commands
 
         public string Name { get; init; }
 
+        public string IconPath { get; init; }
+
+        public IconEvaluator IconEvaluator { get; init; }
+
         public string Display { get; init; }
 
         public string Description { get; init; }
@@ -30,8 +35,13 @@ namespace PixiEditor.Models.Commands
 
         protected abstract object GetParameter();
 
+        protected Command(Action<object> onExecute, CanExecuteEvaluator canExecute) =>
+            Methods = new(this, onExecute, canExecute);
+
         public void Execute() => Methods.Execute(GetParameter());
 
         public bool CanExecute() => Methods.CanExecute(GetParameter());
+
+        public ImageSource GetIcon() => IconEvaluator.EvaluateEvaluator(this, GetParameter());
     }
 }

+ 16 - 0
PixiEditor/Models/Commands/Commands/ToolCommand.cs

@@ -0,0 +1,16 @@
+using PixiEditor.ViewModels;
+
+namespace PixiEditor.Models.Commands
+{
+    public partial class Command
+    {
+        public class ToolCommand : Command
+        {
+            public Type ToolType { get; init; }
+
+            protected override object GetParameter() => ToolType;
+
+            public ToolCommand() : base(ViewModelMain.Current.ToolsSubViewModel.SetTool, CommandController.Current.CanExecuteEvaluators["PixiEditor.HasDocument"]) { }
+        }
+    }
+}

+ 15 - 0
PixiEditor/Models/Commands/Evaluators/CanExecuteEvaluator.cs

@@ -2,5 +2,20 @@
 {
     public class CanExecuteEvaluator : Evaluator<bool>
     {
+        public static CanExecuteEvaluator AlwaysTrue { get; } = new StaticValueEvaluator(true);
+
+        public static CanExecuteEvaluator AlwaysFalse { get; } = new StaticValueEvaluator(false);
+
+        private class StaticValueEvaluator : CanExecuteEvaluator
+        {
+            private readonly bool value;
+
+            public StaticValueEvaluator(bool value)
+            {
+                this.value = value;
+            }
+
+            public override bool EvaluateEvaluator(Command command, object parameter) => value;
+        }
     }
 }

+ 3 - 1
PixiEditor/Models/Commands/Evaluators/Evaluator.cs

@@ -7,6 +7,8 @@ namespace PixiEditor.Models.Commands.Evaluators
     {
         public string Name { get; init; }
 
-        public Func<object, T> Evaluate { get; init; }
+        public Func<object, T> Evaluate { private get; init; }
+
+        public virtual T EvaluateEvaluator(Command command, object parameter) => Evaluate(parameter);
     }
 }

+ 75 - 0
PixiEditor/Models/Commands/Evaluators/IconEvaluator.cs

@@ -0,0 +1,75 @@
+using System.Collections;
+using System.Diagnostics;
+using System.Reflection;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace PixiEditor.Models.Commands.Evaluators
+{
+    public class IconEvaluator : Evaluator<ImageSource>
+    {
+        public static IconEvaluator Default { get; } = new CommandNameEvaluator();
+
+        [DebuggerDisplay("IconEvaluator.Default")]
+        private class CommandNameEvaluator : IconEvaluator
+        {
+            public static string[] resources = GetResourceNames();
+
+            public static Dictionary<string, BitmapImage> images = new();
+
+            public override ImageSource EvaluateEvaluator(Command command, object parameter)
+            {
+                string path;
+
+                if (command.IconPath != null)
+                {
+                    if (command.IconPath.StartsWith('@'))
+                    {
+                        path = command.IconPath[1..];
+                    }
+                    else
+                    {
+                        path = $"Images/{command.IconPath}";
+                    }
+                }
+                else
+                {
+                    path = $"Images/Commands/{command.Name.Replace('.', '/')}.png";
+                }
+
+                path = path.ToLower();
+
+                if (path.StartsWith("/"))
+                {
+                    path = path[1..];
+                }
+
+                if (resources.Contains(path))
+                {
+                    var image = images.GetValueOrDefault(path);
+
+                    if (image == null)
+                    {
+                        image = new BitmapImage(new($"pack://application:,,,/{path}"));
+                        images.Add(path, image);
+                    }
+
+                    return image;
+                }
+
+                return null;
+            }
+
+            private static string[] GetResourceNames()
+            {
+                var assembly = Assembly.GetExecutingAssembly();
+                string resName = assembly.GetName().Name + ".g.resources";
+                using var stream = assembly.GetManifestResourceStream(resName);
+                using var reader = new System.Resources.ResourceReader(stream);
+
+                return reader.Cast<DictionaryEntry>().Select(entry =>
+                         (string)entry.Key).ToArray();
+            }
+        }
+    }
+}

+ 22 - 0
PixiEditor/Models/Commands/Search/CommandSearchResult.cs

@@ -0,0 +1,22 @@
+using PixiEditor.Models.DataHolders;
+using System.Windows.Media;
+
+namespace PixiEditor.Models.Commands.Search
+{
+    public class CommandSearchResult : SearchResult
+    {
+        public Command Command { get; }
+
+        public override string Text => Command.Description;
+
+        public override bool CanExecute => Command.CanExecute();
+
+        public override ImageSource Icon => Command.IconEvaluator.EvaluateEvaluator(Command, this);
+
+        public override KeyCombination Shortcut => Command.Shortcut;
+
+        public CommandSearchResult(Command command) => Command = command;
+
+        public override void Execute() => Command.Execute();
+    }
+}

+ 37 - 0
PixiEditor/Models/Commands/Search/FileSearchResult.cs

@@ -0,0 +1,37 @@
+using PixiEditor.Helpers.Converters;
+using System.IO;
+using System.Windows;
+using System.Windows.Media;
+
+namespace PixiEditor.Models.Commands.Search
+{
+    public class FileSearchResult : SearchResult
+    {
+        private readonly DrawingImage icon;
+
+        public string FilePath { get; }
+
+        public override string Text => $"...\\{Path.GetFileName(FilePath)}";
+
+        public override string Description => FilePath;
+
+        public override bool CanExecute => true;
+
+        public override ImageSource Icon => icon;
+
+        public FileSearchResult(string path)
+        {
+            FilePath = path;
+            icon = new();
+            var drawing = new GeometryDrawing() { Brush = FileExtensionToColorConverter.GetBrush(FilePath) };
+            var geometry = new RectangleGeometry(new(0, 0, 10, 10), 3, 3) { };
+            drawing.Geometry = geometry;
+            icon = new DrawingImage(drawing);
+        }
+
+        public override void Execute()
+        {
+            CommandController.Current.Commands["PixiEditor.File.Open"].Methods.Execute(FilePath);
+        }
+    }
+}

+ 60 - 0
PixiEditor/Models/Commands/Search/SearchResult.cs

@@ -0,0 +1,60 @@
+using GalaSoft.MvvmLight;
+using PixiEditor.Helpers;
+using PixiEditor.Models.DataHolders;
+using System.Text.RegularExpressions;
+using System.Windows.Documents;
+using System.Windows.Media;
+
+namespace PixiEditor.Models.Commands.Search
+{
+    public abstract class SearchResult : ObservableObject
+    {
+        public string SearchTerm { get; init; }
+
+        public virtual Inline[] TextBlockContent => GetInlines().ToArray();
+
+        public Match Match { get; init; }
+
+        public abstract string Text { get; }
+
+        public virtual string Description { get; }
+
+        public abstract bool CanExecute { get; }
+
+        public abstract ImageSource Icon { get; }
+
+        public abstract void Execute();
+
+        public virtual KeyCombination Shortcut { get; }
+
+        public RelayCommand ExecuteCommand { get; }
+
+        public SearchResult()
+        {
+            ExecuteCommand = new(_ => Execute(), _ => CanExecute);
+        }
+
+        private IEnumerable<Inline> GetInlines()
+        {
+            if (Match == null)
+            {
+                yield return new Run(Text);
+                yield break;
+            }
+
+            foreach (Group group in Match.Groups.Values.Skip(1))
+            {
+                var run = new Run(group.Value);
+
+                if (group.Value.Equals(SearchTerm, StringComparison.OrdinalIgnoreCase))
+                {
+                    yield return new Bold(run);
+                }
+                else
+                {
+                    yield return run;
+                }
+            }
+        }
+    }
+}

+ 13 - 17
PixiEditor/Models/Commands/XAML/Command.cs

@@ -22,27 +22,23 @@ namespace PixiEditor.Models.Commands.XAML
 
         public override object ProvideValue(IServiceProvider serviceProvider)
         {
-            try
+            if (commandController == null)
             {
-                if (DesignerProperties.GetIsInDesignMode(serviceProvider.GetService<IProvideValueTarget>().TargetObject as DependencyObject))
-                {
-                    var attribute = DesignCommandHelpers.GetCommandAttribute(Name);
-                    return GetICommand(
-                        new Commands.Command.BasicCommand()
-                        {
-                            Name = Name,
-                            Display = attribute.Display,
-                            Description = attribute.Description,
-                            DefaultShortcut = attribute.GetShortcut(),
-                            Shortcut = attribute.GetShortcut()
-                        }, false);
-                }
+                commandController = ViewModelMain.Current.CommandController;
             }
-            catch { }
 
-            if (commandController == null)
+            if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
             {
-                commandController = ViewModelMain.Current.CommandController;
+                var attribute = DesignCommandHelpers.GetCommandAttribute(Name);
+                return GetICommand(
+                    new Commands.Command.BasicCommand(null, null)
+                    {
+                        Name = Name,
+                        Display = attribute.Display,
+                        Description = attribute.Description,
+                        DefaultShortcut = attribute.GetShortcut(),
+                        Shortcut = attribute.GetShortcut()
+                    }, false);
             }
 
             return GetICommand(commandController.Commands[Name], UseProvided);

+ 5 - 5
PixiEditor/Models/Commands/XAML/ShortcutBinding.cs

@@ -22,15 +22,15 @@ namespace PixiEditor.Models.Commands.XAML
 
         public override object ProvideValue(IServiceProvider serviceProvider)
         {
-            if (DesignerProperties.GetIsInDesignMode(serviceProvider.GetService<IProvideValueTarget>().TargetObject as DependencyObject))
+            if (commandController == null)
             {
-                var attribute = DesignCommandHelpers.GetCommandAttribute(Name);
-                return new KeyCombination(attribute.Key, attribute.Modifiers).ToString();
+                commandController = ViewModelMain.Current.CommandController;
             }
 
-            if (commandController == null)
+            if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
             {
-                commandController = ViewModelMain.Current.CommandController;
+                var attribute = DesignCommandHelpers.GetCommandAttribute(Name);
+                return new KeyCombination(attribute.Key, attribute.Modifiers).ToString();
             }
 
             return GetBinding(commandController.Commands[Name]).ProvideValue(serviceProvider);

+ 0 - 1
PixiEditor/Models/Tools/Tool.cs

@@ -52,7 +52,6 @@ namespace PixiEditor.Models.Tools
         private bool isActive;
         private string actionDisplay = string.Empty;
 
-
         public virtual void OnKeyDown(Key key) { }
 
         public virtual void OnKeyUp(Key key) { }

+ 3 - 2
PixiEditor/Models/Tools/Tools/BrightnessTool.cs

@@ -1,18 +1,19 @@
 using PixiEditor.Helpers;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.Models.Colors;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Settings;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
 using SkiaSharp;
-using System;
-using System.Collections.Generic;
 using System.Windows;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.U)]
     public class BrightnessTool : BitmapOperationTool
     {
         private const float CorrectionFactor = 5f; // Initial correction factor

+ 3 - 0
PixiEditor/Models/Tools/Tools/CircleTool.cs

@@ -1,4 +1,5 @@
 using PixiEditor.Helpers;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Settings;
@@ -7,10 +8,12 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Windows;
+using System.Windows.Input;
 using System.Windows.Media;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.C)]
     public class CircleTool : ShapeTool
     {
         private string defaultActionDisplay = "Click and move mouse to draw a circle. Hold Shift to draw an even one.";

+ 3 - 2
PixiEditor/Models/Tools/Tools/ColorPickerTool.cs

@@ -1,3 +1,4 @@
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.ImageManipulation;
@@ -6,11 +7,11 @@ using PixiEditor.Models.Position;
 using PixiEditor.Models.Services;
 using PixiEditor.ViewModels;
 using SkiaSharp;
-using System;
-using System.Collections.Generic;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.O)]
     internal class ColorPickerTool : ReadonlyTool
     {
         private readonly DocumentProvider _docProvider;

+ 4 - 2
PixiEditor/Models/Tools/Tools/EraserTool.cs

@@ -1,13 +1,15 @@
-using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Commands.Attributes;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Settings;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
 using SkiaSharp;
-using System.Collections.Generic;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.E)]
     internal class EraserTool : BitmapOperationTool
     {
         private readonly PenTool pen;

+ 3 - 1
PixiEditor/Models/Tools/Tools/FloodFillTool.cs

@@ -1,13 +1,15 @@
 using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using SkiaSharp;
-using System.Collections.Generic;
 using System.Windows;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.G)]
     internal class FloodFillTool : BitmapOperationTool
     {
         private BitmapManager BitmapManager { get; }

+ 3 - 2
PixiEditor/Models/Tools/Tools/LineTool.cs

@@ -1,15 +1,16 @@
 using PixiEditor.Helpers;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Settings;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
 using SkiaSharp;
-using System;
-using System.Collections.Generic;
 using System.Windows;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.L)]
     public class LineTool : ShapeTool
     {
         private List<Coordinates> linePoints = new List<Coordinates>();

+ 3 - 1
PixiEditor/Models/Tools/Tools/MagicWandTool.cs

@@ -1,5 +1,6 @@
 using PixiEditor.Helpers;
 using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
@@ -9,12 +10,13 @@ using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
 using PixiEditor.ViewModels;
 using SkiaSharp;
-using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Windows;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.W)]
     internal class MagicWandTool : ReadonlyTool, ICachedDocumentTool
     {
         private static Selection ActiveSelection { get => ViewModelMain.Current.BitmapManager.ActiveDocument.ActiveSelection; }

+ 2 - 2
PixiEditor/Models/Tools/Tools/MoveTool.cs

@@ -1,4 +1,5 @@
 using PixiEditor.Helpers;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
@@ -7,13 +8,12 @@ using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Undo;
 using SkiaSharp;
-using System.Collections.Generic;
-using System.Linq;
 using System.Windows;
 using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.V)]
     internal class MoveTool : BitmapOperationTool
     {
         private Layer[] affectedLayers;

+ 4 - 2
PixiEditor/Models/Tools/Tools/MoveViewportTool.cs

@@ -1,9 +1,11 @@
-using PixiEditor.Models.Position;
+using PixiEditor.Models.Commands.Attributes;
+using PixiEditor.Models.Position;
 using System.Collections.Generic;
 using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
-{
+{
+    [Command.Tool(Key = Key.H)]
     public class MoveViewportTool : ReadonlyTool
     {
         public MoveViewportTool()

+ 3 - 4
PixiEditor/Models/Tools/Tools/PenTool.cs

@@ -1,18 +1,17 @@
-using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Commands.Attributes;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.Brushes;
 using PixiEditor.Models.Tools.ToolSettings.Settings;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
 using SkiaSharp;
-using System;
-using System.Collections.Generic;
-using System.Linq;
 using System.Windows;
 using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.B)]
     internal class PenTool : ShapeTool
     {
         public Brush Brush { get; set; }

+ 3 - 2
PixiEditor/Models/Tools/Tools/RectangleTool.cs

@@ -1,14 +1,15 @@
 using PixiEditor.Helpers;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Settings;
 using SkiaSharp;
-using System;
-using System.Collections.Generic;
 using System.Windows;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.R)]
     public class RectangleTool : ShapeTool
     {
         private string defaultActionDisplay = "Click and move to draw a rectangle. Hold Shift to draw a square.";

+ 4 - 3
PixiEditor/Models/Tools/Tools/SelectTool.cs

@@ -1,5 +1,6 @@
 using PixiEditor.Helpers;
 using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.Commands.Attributes;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Enums;
@@ -7,13 +8,13 @@ using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools.ToolSettings.Toolbars;
 using PixiEditor.ViewModels;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
 using SkiaSharp;
+using System.Collections.ObjectModel;
+using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
 {
+    [Command.Tool(Key = Key.M)]
     internal class SelectTool : ReadonlyTool
     {
         private readonly RectangleTool rectangleTool;

+ 4 - 3
PixiEditor/Models/Tools/Tools/ZoomTool.cs

@@ -1,10 +1,11 @@
-using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Commands.Attributes;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Position;
-using System.Collections.Generic;
 using System.Windows.Input;
 
 namespace PixiEditor.Models.Tools.Tools
-{
+{
+    [Command.Tool(Key = Key.Z)]
     internal class ZoomTool : ReadonlyTool
     {
         private BitmapManager BitmapManager { get; }

+ 14 - 0
PixiEditor/PixiEditor.csproj

@@ -137,6 +137,13 @@
 		<None Remove="Images\AnchorDot.png" />
 		<None Remove="Images\CheckerTile.png" />
 		<None Remove="Images\ChevronDown.png" />
+		<None Remove="Images\Commands\PixiEditor\Clipboard\Copy.png" />
+		<None Remove="Images\Commands\PixiEditor\Clipboard\Cut.png" />
+		<None Remove="Images\Commands\PixiEditor\Clipboard\Paste.png" />
+		<None Remove="Images\Commands\PixiEditor\Colors\Swap.png" />
+		<None Remove="Images\Commands\PixiEditor\Document\CenterContent.png" />
+		<None Remove="Images\Commands\PixiEditor\Document\ResizeCanvas.png" />
+		<None Remove="Images\Commands\PixiEditor\Document\ResizeDocument.png" />
 		<None Remove="Images\DiagonalRed.png" />
 		<None Remove="Images\Eye-off.png" />
 		<None Remove="Images\Eye.png" />
@@ -210,6 +217,13 @@
 		<Resource Include="Images\AnchorDot.png" />
 		<Resource Include="Images\CheckerTile.png" />
 		<Resource Include="Images\ChevronDown.png" />
+		<Resource Include="Images\Commands\PixiEditor\Clipboard\Copy.png" />
+		<Resource Include="Images\Commands\PixiEditor\Clipboard\Cut.png" />
+		<Resource Include="Images\Commands\PixiEditor\Clipboard\Paste.png" />
+		<Resource Include="Images\Commands\PixiEditor\Colors\Swap.png" />
+		<Resource Include="Images\Commands\PixiEditor\Document\CenterContent.png" />
+		<Resource Include="Images\Commands\PixiEditor\Document\ResizeCanvas.png" />
+		<Resource Include="Images\Commands\PixiEditor\Document\ResizeDocument.png" />
 		<Resource Include="Images\DiagonalRed.png" />
 		<Resource Include="Images\Eye-off.png" />
 		<Resource Include="Images\Eye.png" />

+ 2 - 1
PixiEditor/Styles/ThemeStyle.xaml

@@ -172,7 +172,8 @@
                 <ControlTemplate TargetType="TextBox">
                     <Border Background="{TemplateBinding Background}"
                             BorderBrush="{TemplateBinding BorderBrush}"
-                            BorderThickness="{TemplateBinding BorderThickness}">
+                            BorderThickness="{TemplateBinding BorderThickness}"
+                            Padding="{TemplateBinding Padding}">
                         <ScrollViewer Name="PART_ContentHost"/>
                     </Border>
                 </ControlTemplate>

+ 84 - 0
PixiEditor/ViewModels/CommandSearchViewModel.cs

@@ -0,0 +1,84 @@
+using PixiEditor.Helpers;
+using PixiEditor.Models.Commands;
+using PixiEditor.Models.Commands.Search;
+using System.Collections.ObjectModel;
+using System.Text.RegularExpressions;
+
+namespace PixiEditor.ViewModels
+{
+    public class CommandSearchViewModel : NotifyableObject
+    {
+        private string searchTerm;
+        private SearchResult selectedCommand;
+
+        public string SearchTerm
+        {
+            get => searchTerm;
+            set
+            {
+                if (SetProperty(ref searchTerm, value))
+                {
+                    UpdateSearchResults();
+                }
+            }
+        }
+
+        public SearchResult SelectedResult
+        {
+            get => selectedCommand;
+            set => SetProperty(ref selectedCommand, value);
+        }
+
+        public ObservableCollection<SearchResult> Commands { get; } = new();
+
+        public CommandSearchViewModel()
+        {
+            UpdateSearchResults();
+        }
+
+        private void UpdateSearchResults()
+        {
+            CommandController controller = CommandController.Current;
+            Commands.Clear();
+
+            if (string.IsNullOrWhiteSpace(SearchTerm))
+            {
+                foreach (var file in ViewModelMain.Current.FileSubViewModel.RecentlyOpened)
+                {
+                    Commands.Add(
+                        new FileSearchResult(file.FilePath)
+                        {
+                            SearchTerm = searchTerm
+                        });
+                }
+
+                return;
+            }
+
+            foreach (var command in controller.Commands
+                .Where(x => x.Description.Contains(SearchTerm, StringComparison.OrdinalIgnoreCase))
+                .OrderByDescending(x => x.Description.Contains($" {SearchTerm} ", StringComparison.OrdinalIgnoreCase))
+                .Take(12))
+            {
+                Commands.Add(
+                    new CommandSearchResult(command)
+                    {
+                        SearchTerm = searchTerm,
+                        Match = Match(command.Description)
+                    });
+            }
+
+            foreach (var file in ViewModelMain.Current.FileSubViewModel.RecentlyOpened.Where(x => x.FilePath.Contains(searchTerm)))
+            {
+                Commands.Add(
+                    new FileSearchResult(file.FilePath)
+                    {
+                        SearchTerm = searchTerm,
+                        Match = Match(file.FilePath)
+                    });
+            }
+
+            Match Match(string text) => Regex.Match(text, $"(.*)({Regex.Escape(SearchTerm)})(.*)", RegexOptions.IgnoreCase);
+        }
+    }
+}

+ 1 - 1
PixiEditor/ViewModels/SubViewModels/Main/DocumentViewModel.cs

@@ -62,7 +62,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             Owner.BitmapManager.CloseDocument(document);
         }
 
-        [Command.Basic("PixiEditor.Document.DeletePixels", "Delete pixels", "Delete selected pixels", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.Delete)]
+        [Command.Basic("PixiEditor.Document.DeletePixels", "Delete pixels", "Delete selected pixels", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.Delete, Icon = "Tools/EraserImage.png")]
         public void DeletePixels()
         {
             var doc = Owner.BitmapManager.ActiveDocument;

+ 1 - 1
PixiEditor/ViewModels/SubViewModels/Main/LayersViewModel.cs

@@ -202,7 +202,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             return Owner.BitmapManager.ActiveDocument?.Layers.Count(x => x.IsActive) > 0;
         }
 
-        [Command.Basic("PixiEditor.Layer.New", "New Layer", "Create new layer", CanExecute = "PixiEditor.HasDocument", Key = Key.N, Modifiers = ModifierKeys.Control | ModifierKeys.Shift)]
+        [Command.Basic("PixiEditor.Layer.New", "New Layer", "Create new layer", CanExecute = "PixiEditor.HasDocument", Key = Key.N, Modifiers = ModifierKeys.Control | ModifierKeys.Shift, Icon = "Layer-add.png")]
         public void NewLayer(object parameter)
         {
             GuidStructureItem control = GetGroupFromParameter(parameter);

+ 276 - 273
PixiEditor/Views/MainWindow.xaml

@@ -61,74 +61,75 @@
             <cmd:EventToCommand Command="{Binding CloseWindowCommand}" PassEventArgsToCommand="True" />
         </i:EventTrigger>
     </i:Interaction.Triggers>
-    <Grid Name="mainGrid" Margin="5" Focusable="True" >
-        <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="45" />
-            <ColumnDefinition Width="1*" />
-        </Grid.ColumnDefinitions>
-        <Grid.RowDefinitions>
-            <RowDefinition Height="30" />
-            <RowDefinition Height="40" />
-            <RowDefinition Height="1*" />
-            <RowDefinition Height="30" />
-        </Grid.RowDefinitions>
-        <i:Interaction.Behaviors>
-            <behaviours:ClearFocusOnClickBehavior/>
-        </i:Interaction.Behaviors>
-        <DockPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Background="{StaticResource MainColor}">
-            <Image DockPanel.Dock="Left" HorizontalAlignment="Left" VerticalAlignment="Top"
+    <Grid>
+        <Grid Name="mainGrid" Margin="5" Focusable="True" >
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="45" />
+                <ColumnDefinition Width="1*" />
+            </Grid.ColumnDefinitions>
+            <Grid.RowDefinitions>
+                <RowDefinition Height="30" />
+                <RowDefinition Height="40" />
+                <RowDefinition Height="1*" />
+                <RowDefinition Height="30" />
+            </Grid.RowDefinitions>
+            <i:Interaction.Behaviors>
+                <behaviours:ClearFocusOnClickBehavior/>
+            </i:Interaction.Behaviors>
+            <DockPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Background="{StaticResource MainColor}">
+                <Image DockPanel.Dock="Left" HorizontalAlignment="Left" VerticalAlignment="Top"
                    Source="/Images/PixiEditorLogo.png" Width="20" Height="20" Margin="5,5,0,0" />
-            <cmds:Menu WindowChrome.IsHitTestVisibleInChrome="True" Margin="10, 4, 0, 0" DockPanel.Dock="Left"
+                <cmds:Menu WindowChrome.IsHitTestVisibleInChrome="True" Margin="10, 4, 0, 0" DockPanel.Dock="Left"
                   HorizontalAlignment="Left" VerticalAlignment="Top" Background="Transparent" IsMainMenu="True">
-                <Menu.Resources>
-                    <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource menuItemStyle}" />
-                </Menu.Resources>
-                <MenuItem Header="_File">
-                    <MenuItem Header="_New" cmds:Menu.Command="PixiEditor.File.New" />
-                    <MenuItem Header="_Open" cmds:Menu.Command="PixiEditor.File.Open" />
-                    <MenuItem Header="_Recent" ItemsSource="{Binding FileSubViewModel.RecentlyOpened}" x:Name="recentItemMenu" IsEnabled="{Binding FileSubViewModel.HasRecent}">
-                        <MenuItem.ItemContainerStyle>
-                            <Style TargetType="MenuItem" BasedOn="{StaticResource PixiEditorDockThemeMenuItemStyle}">
-                                <Setter Property="Command" Value="{cmds:Command PixiEditor.File.Open, UseProvided=True}"/>
-                                <Setter Property="CommandParameter" Value="{Binding FilePath}"/>
-                            </Style>
-                        </MenuItem.ItemContainerStyle>
-                        <MenuItem.ItemTemplate>
-                            <DataTemplate DataType="{x:Type dataHolders:RecentlyOpenedDocument}">
-                                <TextBlock Text="{Binding FilePath}"/>
-                            </DataTemplate>
-                        </MenuItem.ItemTemplate>
+                    <Menu.Resources>
+                        <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource menuItemStyle}" />
+                    </Menu.Resources>
+                    <MenuItem Header="_File">
+                        <MenuItem Header="_New" cmds:Menu.Command="PixiEditor.File.New" />
+                        <MenuItem Header="_Open" cmds:Menu.Command="PixiEditor.File.Open" />
+                        <MenuItem Header="_Recent" ItemsSource="{Binding FileSubViewModel.RecentlyOpened}" x:Name="recentItemMenu" IsEnabled="{Binding FileSubViewModel.HasRecent}">
+                            <MenuItem.ItemContainerStyle>
+                                <Style TargetType="MenuItem" BasedOn="{StaticResource PixiEditorDockThemeMenuItemStyle}">
+                                    <Setter Property="Command" Value="{cmds:Command PixiEditor.File.Open, UseProvided=True}"/>
+                                    <Setter Property="CommandParameter" Value="{Binding FilePath}"/>
+                                </Style>
+                            </MenuItem.ItemContainerStyle>
+                            <MenuItem.ItemTemplate>
+                                <DataTemplate DataType="{x:Type dataHolders:RecentlyOpenedDocument}">
+                                    <TextBlock Text="{Binding FilePath}"/>
+                                </DataTemplate>
+                            </MenuItem.ItemTemplate>
+                        </MenuItem>
+                        <MenuItem Header="_Save" cmds:Menu.Command="PixiEditor.File.Save" />
+                        <MenuItem Header="_Save As..." cmds:Menu.Command="PixiEditor.File.SaveAsNew" />
+                        <MenuItem Header="_Export" cmds:Menu.Command="PixiEditor.File.Export" />
+                        <Separator />
+                        <MenuItem Header="_Exit" Command="{x:Static SystemCommands.CloseWindowCommand}" />
                     </MenuItem>
-                    <MenuItem Header="_Save" cmds:Menu.Command="PixiEditor.File.Save" />
-                    <MenuItem Header="_Save As..." cmds:Menu.Command="PixiEditor.File.SaveAsNew" />
-                    <MenuItem Header="_Export" cmds:Menu.Command="PixiEditor.File.Export" />
-                    <Separator />
-                    <MenuItem Header="_Exit" Command="{x:Static SystemCommands.CloseWindowCommand}" />
-                </MenuItem>
-                <MenuItem Header="_Edit">
-                    <MenuItem Header="_Undo" cmds:Menu.Command="PixiEditor.Undo.Undo" />
-                    <MenuItem Header="_Redo" cmds:Menu.Command="PixiEditor.Undo.Redo" />
-                    <Separator />
-                    <MenuItem Header="_Cut" cmds:Menu.Command="PixiEditor.Clipboard.Cut" />
-                    <MenuItem Header="_Copy" cmds:Menu.Command="PixiEditor.Clipboard.Copy" />
-                    <MenuItem Header="_Paste" cmds:Menu.Command="PixiEditor.Clipboard.Paste" />
-                    <MenuItem Header="_Duplicate" cmds:Menu.Command="PixiEditor.Clipboard.Duplicate" />
-                    <Separator />
-                    <MenuItem Header="_Delete Selected" cmds:Menu.Command="PixiEditor.Document.DeletePixels" />
-                    <Separator />
-                    <MenuItem Header="_Settings" cmds:Menu.Command="PixiEditor.Settings.Open" />
-                </MenuItem>
-                <MenuItem Header="_Select">
-                    <MenuItem Header="_Select All" cmds:Menu.Command="PixiEditor.Selection.SelectAll" />
-                    <MenuItem Header="_Deselect" cmds:Menu.Command="PixiEditor.Selection.Clear" />
-                </MenuItem>
-                <MenuItem Header="_Image">
-                    <MenuItem Header="Resize _Image..." cmds:Menu.Command="PixiEditor.Document.ResizeDocument" />
-                    <MenuItem Header="_Resize Canvas..." cmds:Menu.Command="PixiEditor.Document.ResizeCanvas" />
-                    <MenuItem Header="_Clip Canvas" cmds:Menu.Command="PixiEditor.Document.ClipCanvas" />
-                    <Separator/>
-                    <MenuItem Header="_Center Content" cmds:Menu.Command="PixiEditor.Document.CenterContent" />
-                    <!--<Separator/>
+                    <MenuItem Header="_Edit">
+                        <MenuItem Header="_Undo" cmds:Menu.Command="PixiEditor.Undo.Undo" />
+                        <MenuItem Header="_Redo" cmds:Menu.Command="PixiEditor.Undo.Redo" />
+                        <Separator />
+                        <MenuItem Header="_Cut" cmds:Menu.Command="PixiEditor.Clipboard.Cut" />
+                        <MenuItem Header="_Copy" cmds:Menu.Command="PixiEditor.Clipboard.Copy" />
+                        <MenuItem Header="_Paste" cmds:Menu.Command="PixiEditor.Clipboard.Paste" />
+                        <MenuItem Header="_Duplicate" cmds:Menu.Command="PixiEditor.Clipboard.Duplicate" />
+                        <Separator />
+                        <MenuItem Header="_Delete Selected" cmds:Menu.Command="PixiEditor.Document.DeletePixels" />
+                        <Separator />
+                        <MenuItem Header="_Settings" cmds:Menu.Command="PixiEditor.Settings.Open" />
+                    </MenuItem>
+                    <MenuItem Header="_Select">
+                        <MenuItem Header="_Select All" cmds:Menu.Command="PixiEditor.Selection.SelectAll" />
+                        <MenuItem Header="_Deselect" cmds:Menu.Command="PixiEditor.Selection.Clear" />
+                    </MenuItem>
+                    <MenuItem Header="_Image">
+                        <MenuItem Header="Resize _Image..." cmds:Menu.Command="PixiEditor.Document.ResizeDocument" />
+                        <MenuItem Header="_Resize Canvas..." cmds:Menu.Command="PixiEditor.Document.ResizeCanvas" />
+                        <MenuItem Header="_Clip Canvas" cmds:Menu.Command="PixiEditor.Document.ClipCanvas" />
+                        <Separator/>
+                        <MenuItem Header="_Center Content" cmds:Menu.Command="PixiEditor.Document.CenterContent" />
+                        <!--<Separator/>
                     <MenuItem Header="_Rotate to right 90&#186;" Command="{Binding DocumentSubViewModel.RotateToRightCommand}">
                         <MenuItem.CommandParameter>
                             <sys:Double>90</sys:Double>
@@ -143,132 +144,132 @@
                     <MenuItem Header="_Flip Horizontal" Command="{Binding DocumentSubViewModel.FlipCommand}" CommandParameter="Horizontal"/>
                     <MenuItem Header="_Flip Vertical" Command="{Binding DocumentSubViewModel.FlipCommand}" CommandParameter="Vertical"/>
                 -->
-                </MenuItem>
-                <MenuItem Header="_View">
-                    <MenuItem Header="_Show Grid Lines" IsChecked="{Binding ViewportSubViewModel.GridLinesEnabled, Mode=TwoWay}"
+                    </MenuItem>
+                    <MenuItem Header="_View">
+                        <MenuItem Header="_Show Grid Lines" IsChecked="{Binding ViewportSubViewModel.GridLinesEnabled, Mode=TwoWay}"
                               IsCheckable="True" InputGestureText="{cmds:ShortcutBinding PixiEditor.View.ToggleGrid}"/>
-                    <MenuItem Header="Open _Startup Window" ToolTip="Hello there!" cmds:Menu.Command="PixiEditor.Window.OpenStartupWindow"/>
-                    <MenuItem Header="Open _Navigation Window" cmds:Menu.Command="PixiEditor.Window.OpenNavigationWindow"/>
-                </MenuItem>
-                <MenuItem Header="_Help">
-                    <MenuItem Header="_Documentation" cmds:Menu.Command="PixiEditor.Links.OpenDocumentation" />
-                    <MenuItem Header="_Website" cmds:Menu.Command="PixiEditor.Links.OpenWebsite" />
-                    <MenuItem Header="_Repository" cmds:Menu.Command="PixiEditor.Links.OpenRepository" />
-                    <Separator/>
-                    <MenuItem Header="_License" cmds:Menu.Command="PixiEditor.Links.OpenLicense" />
-                    <MenuItem Header="_Third Party Licenses" cmds:Menu.Command="PixiEditor.Links.OpenOtherLicenses" />
-                </MenuItem>
-                <MenuItem Header="_Debug" Visibility="{Binding DebugSubViewModel.UseDebug, Converter={StaticResource BoolToVisibilityConverter}}">
-                    <MenuItem Header="Open _Local App Data" cmds:Menu.Command="PixiEditor.Debug.OpenLocalAppDataDirectory" />
-                    <MenuItem Header="Open _Roaming App Data" cmds:Menu.Command="PixiEditor.Debug.OpenRoamingAppDataDirectory" />
-                    <MenuItem Header="Open _Temp App Data" cmds:Menu.Command="PixiEditor.Debug.OpenTempDirectory" />
-                    <MenuItem Header="Open _Install Location" cmds:Menu.Command="PixiEditor.Debug.OpenInstallDirectory" />
-                    <Separator/>
-                    <MenuItem Header="_Crash" cmds:Menu.Command="PixiEditor.Debug.Crash" />
-                    <MenuItem Header="Delete">
-                        <MenuItem Header="User Preferences (Roaming)" cmds:Menu.Command="PixiEditor.Debug.DeleteUserPreferences" />
-                        <MenuItem Header="Editor Data (Local)" cmds:Menu.Command="PixiEditor.Debug.DeleteEditorData" />
+                        <MenuItem Header="Open _Startup Window" ToolTip="Hello there!" cmds:Menu.Command="PixiEditor.Window.OpenStartupWindow"/>
+                        <MenuItem Header="Open _Navigation Window" cmds:Menu.Command="PixiEditor.Window.OpenNavigationWindow"/>
                     </MenuItem>
-                </MenuItem>
-            </cmds:Menu>
-            <StackPanel DockPanel.Dock="Right" VerticalAlignment="Top" Orientation="Horizontal" Margin="0,-5,-5,0"
+                    <MenuItem Header="_Help">
+                        <MenuItem Header="_Documentation" cmds:Menu.Command="PixiEditor.Links.OpenDocumentation" />
+                        <MenuItem Header="_Website" cmds:Menu.Command="PixiEditor.Links.OpenWebsite" />
+                        <MenuItem Header="_Repository" cmds:Menu.Command="PixiEditor.Links.OpenRepository" />
+                        <Separator/>
+                        <MenuItem Header="_License" cmds:Menu.Command="PixiEditor.Links.OpenLicense" />
+                        <MenuItem Header="_Third Party Licenses" cmds:Menu.Command="PixiEditor.Links.OpenOtherLicenses" />
+                    </MenuItem>
+                    <MenuItem Header="_Debug" Visibility="{Binding DebugSubViewModel.UseDebug, Converter={StaticResource BoolToVisibilityConverter}}">
+                        <MenuItem Header="Open _Local App Data" cmds:Menu.Command="PixiEditor.Debug.OpenLocalAppDataDirectory" />
+                        <MenuItem Header="Open _Roaming App Data" cmds:Menu.Command="PixiEditor.Debug.OpenRoamingAppDataDirectory" />
+                        <MenuItem Header="Open _Temp App Data" cmds:Menu.Command="PixiEditor.Debug.OpenTempDirectory" />
+                        <MenuItem Header="Open _Install Location" cmds:Menu.Command="PixiEditor.Debug.OpenInstallDirectory" />
+                        <Separator/>
+                        <MenuItem Header="_Crash" cmds:Menu.Command="PixiEditor.Debug.Crash" />
+                        <MenuItem Header="Delete">
+                            <MenuItem Header="User Preferences (Roaming)" cmds:Menu.Command="PixiEditor.Debug.DeleteUserPreferences" />
+                            <MenuItem Header="Editor Data (Local)" cmds:Menu.Command="PixiEditor.Debug.DeleteEditorData" />
+                        </MenuItem>
+                    </MenuItem>
+                </cmds:Menu>
+                <StackPanel DockPanel.Dock="Right" VerticalAlignment="Top" Orientation="Horizontal" Margin="0,-5,-5,0"
                         HorizontalAlignment="Right" WindowChrome.IsHitTestVisibleInChrome="True">
-                <Button Style="{StaticResource MinimizeButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True"
+                    <Button Style="{StaticResource MinimizeButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True"
                         ToolTip="Minimize"
                         Command="{x:Static SystemCommands.MinimizeWindowCommand}" />
-                <Button x:Name="RestoreButton" Visibility="Visible" Style="{StaticResource RestoreButtonStyle}"
+                    <Button x:Name="RestoreButton" Visibility="Visible" Style="{StaticResource RestoreButtonStyle}"
                         Command="{x:Static SystemCommands.RestoreWindowCommand}"
                         WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Restore" />
-                <Button x:Name="MaximizeButton" Visibility="Collapsed" Style="{StaticResource MaximizeButtonStyle}"
+                    <Button x:Name="MaximizeButton" Visibility="Collapsed" Style="{StaticResource MaximizeButtonStyle}"
                         Command="{x:Static SystemCommands.MaximizeWindowCommand}"
                         WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Maximize" />
-                <Button Style="{StaticResource CloseButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True"
+                    <Button Style="{StaticResource CloseButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True"
                         ToolTip="Close"
                         Command="{x:Static SystemCommands.CloseWindowCommand}" />
-            </StackPanel>
-        </DockPanel>
-        <StackPanel Background="{StaticResource MainColor}" Orientation="Horizontal" Grid.ColumnSpan="3" Grid.Column="0"
+                </StackPanel>
+            </DockPanel>
+            <StackPanel Background="{StaticResource MainColor}" Orientation="Horizontal" Grid.ColumnSpan="3" Grid.Column="0"
                      Grid.Row="1">
-            <Button Margin="1,0,0,0" Command="{cmds:Command PixiEditor.Undo.Undo}" ToolTip="Undo"
+                <Button Margin="1,0,0,0" Command="{cmds:Command PixiEditor.Undo.Undo}" ToolTip="Undo"
                     Style="{StaticResource ToolSettingsGlyphButton}" Content="&#xE7A7;"/>
-            <Button Command="{cmds:Command PixiEditor.Undo.Redo}" ToolTip="Redo"
+                <Button Command="{cmds:Command PixiEditor.Undo.Redo}" ToolTip="Redo"
                     Style="{StaticResource ToolSettingsGlyphButton}" Content="&#xE7A6;"/>
-            <ToggleButton Width="30" BorderThickness="0"
+                <ToggleButton Width="30" BorderThickness="0"
                           ToolTip="Pen Mode" Focusable="False"
                           IsChecked="{Binding StylusSubViewModel.IsPenModeEnabled}">
-                <ToggleButton.Style>
-                    <Style TargetType="ToggleButton">
-                        <Setter Property="Template">
-                            <Setter.Value>
-                                <ControlTemplate TargetType="ToggleButton">
-                                    <Border BorderBrush="{TemplateBinding BorderBrush}" 
+                    <ToggleButton.Style>
+                        <Style TargetType="ToggleButton">
+                            <Setter Property="Template">
+                                <Setter.Value>
+                                    <ControlTemplate TargetType="ToggleButton">
+                                        <Border BorderBrush="{TemplateBinding BorderBrush}" 
                                             Background="{TemplateBinding Background}" Focusable="False">
-                                        <ContentPresenter HorizontalAlignment="Center"
+                                            <ContentPresenter HorizontalAlignment="Center"
                                               VerticalAlignment="Center" Focusable="False"/>
-                                    </Border>
-                                </ControlTemplate>
-                            </Setter.Value>
-                        </Setter>
-                        <Style.Triggers>
-                            <Trigger Property="IsChecked" Value="False">
-                                <Setter Property="Background" Value="Transparent"/>
-                            </Trigger>
-                            <Trigger Property="IsMouseOver" Value="True">
-                                <Setter Property="Background" Value="#404040"/>
-                            </Trigger>
-                            <Trigger Property="IsChecked" Value="True">
-                                <Setter Property="Background" Value="#707070"/>
-                            </Trigger>
-                        </Style.Triggers>
-                    </Style>
-                </ToggleButton.Style>
-                <Image Height="20" Source="../Images/penMode.png"/>
-            </ToggleButton>
-            <Grid Margin="5,5,10,5" Background="{StaticResource BrighterAccentColor}" Width="5"/>
-            <Label Style="{StaticResource BaseLabel}" FontSize="12"
+                                        </Border>
+                                    </ControlTemplate>
+                                </Setter.Value>
+                            </Setter>
+                            <Style.Triggers>
+                                <Trigger Property="IsChecked" Value="False">
+                                    <Setter Property="Background" Value="Transparent"/>
+                                </Trigger>
+                                <Trigger Property="IsMouseOver" Value="True">
+                                    <Setter Property="Background" Value="#404040"/>
+                                </Trigger>
+                                <Trigger Property="IsChecked" Value="True">
+                                    <Setter Property="Background" Value="#707070"/>
+                                </Trigger>
+                            </Style.Triggers>
+                        </Style>
+                    </ToggleButton.Style>
+                    <Image Height="20" Source="../Images/penMode.png"/>
+                </ToggleButton>
+                <Grid Margin="5,5,10,5" Background="{StaticResource BrighterAccentColor}" Width="5"/>
+                <Label Style="{StaticResource BaseLabel}" FontSize="12"
                    VerticalAlignment="Center" Content="{Binding ToolsSubViewModel.ActiveTool.DisplayName}"
                    ToolTip="{Binding ToolsSubViewModel.ActiveTool.ActionDisplay}"/>
-            <ItemsControl ItemsSource="{Binding ToolsSubViewModel.ActiveTool.Toolbar.Settings}">
-                <ItemsControl.ItemsPanel>
-                    <ItemsPanelTemplate>
-                        <StackPanel Orientation="Horizontal" Margin="10, 0, 0, 0" />
-                    </ItemsPanelTemplate>
-                </ItemsControl.ItemsPanel>
-                <ItemsControl.ItemTemplate>
-                    <DataTemplate>
-                        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="10,0,10,0">
-                            <Label
+                <ItemsControl ItemsSource="{Binding ToolsSubViewModel.ActiveTool.Toolbar.Settings}">
+                    <ItemsControl.ItemsPanel>
+                        <ItemsPanelTemplate>
+                            <StackPanel Orientation="Horizontal" Margin="10, 0, 0, 0" />
+                        </ItemsPanelTemplate>
+                    </ItemsControl.ItemsPanel>
+                    <ItemsControl.ItemTemplate>
+                        <DataTemplate>
+                            <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="10,0,10,0">
+                                <Label
                                 Visibility="{Binding HasLabel, Converter={StaticResource BoolToVisibilityConverter}}"
                                 Foreground="White" Content="{Binding Label}" />
-                            <ContentControl Content="{Binding SettingControl}" />
-                        </StackPanel>
-                    </DataTemplate>
-                </ItemsControl.ItemTemplate>
-            </ItemsControl>
-        </StackPanel>
-        <Grid Grid.Column="1" Grid.Row="2" Background="#303030" >
-            <Grid AllowDrop="True" Drop="MainWindow_Drop">
-                <DockingManager ActiveContent="{Binding BitmapManager.ActiveWindow, Mode=TwoWay}"
+                                <ContentControl Content="{Binding SettingControl}" />
+                            </StackPanel>
+                        </DataTemplate>
+                    </ItemsControl.ItemTemplate>
+                </ItemsControl>
+            </StackPanel>
+            <Grid Grid.Column="1" Grid.Row="2" Background="#303030" >
+                <Grid AllowDrop="True" Drop="MainWindow_Drop">
+                    <DockingManager ActiveContent="{Binding BitmapManager.ActiveWindow, Mode=TwoWay}"
                                            DocumentsSource="{Binding BitmapManager.Documents}">
-                    <DockingManager.Theme>
-                        <avalonDockTheme:PixiEditorDockTheme />
-                    </DockingManager.Theme>
+                        <DockingManager.Theme>
+                            <avalonDockTheme:PixiEditorDockTheme />
+                        </DockingManager.Theme>
 
-                    <avalondock:DockingManager.LayoutItemContainerStyleSelector>
-                        <ui:PanelsStyleSelector>
-                            <ui:PanelsStyleSelector.DocumentTabStyle>
-                                <Style TargetType="{x:Type avalondock:LayoutItem}">
-                                    <Setter Property="Title" Value="{Binding Model.Name}" />
-                                    <Setter Property="CloseCommand" Value="{Binding Model.RequestCloseDocumentCommand}" />
-                                </Style>
-                            </ui:PanelsStyleSelector.DocumentTabStyle>
-                        </ui:PanelsStyleSelector>
-                    </avalondock:DockingManager.LayoutItemContainerStyleSelector>
-                    <DockingManager.LayoutItemTemplateSelector>
-                        <ui:DocumentsTemplateSelector>
-                            <ui:DocumentsTemplateSelector.DocumentsViewTemplate>
-                                <DataTemplate DataType="{x:Type dataHolders:Document}">
-                                    <usercontrols:DrawingViewPort
+                        <avalondock:DockingManager.LayoutItemContainerStyleSelector>
+                            <ui:PanelsStyleSelector>
+                                <ui:PanelsStyleSelector.DocumentTabStyle>
+                                    <Style TargetType="{x:Type avalondock:LayoutItem}">
+                                        <Setter Property="Title" Value="{Binding Model.Name}" />
+                                        <Setter Property="CloseCommand" Value="{Binding Model.RequestCloseDocumentCommand}" />
+                                    </Style>
+                                </ui:PanelsStyleSelector.DocumentTabStyle>
+                            </ui:PanelsStyleSelector>
+                        </avalondock:DockingManager.LayoutItemContainerStyleSelector>
+                        <DockingManager.LayoutItemTemplateSelector>
+                            <ui:DocumentsTemplateSelector>
+                                <ui:DocumentsTemplateSelector.DocumentsViewTemplate>
+                                    <DataTemplate DataType="{x:Type dataHolders:Document}">
+                                        <usercontrols:DrawingViewPort
                                         CenterViewportTrigger="{Binding CenterViewportTrigger}"
                                         ZoomViewportTrigger="{Binding ZoomViewportTrigger}"
                                         GridLinesVisible="{Binding XamlAccesibleViewModel.ViewportSubViewModel.GridLinesEnabled}"
@@ -287,148 +288,150 @@
                                         IsUsingZoomTool="{Binding XamlAccesibleViewModel.ToolsSubViewModel.ActiveTool, Converter={converters:IsSpecifiedTypeConverter SpecifiedType={x:Type tools:ZoomTool}}}"
                                         IsUsingMoveViewportTool="{Binding XamlAccesibleViewModel.ToolsSubViewModel.ActiveTool, Converter={converters:IsSpecifiedTypeConverter SpecifiedType={x:Type tools:MoveViewportTool}}}"
                                         Stylus.IsTapFeedbackEnabled="False" Stylus.IsTouchFeedbackEnabled="False">
-                                        <i:Interaction.Triggers>
-                                            <i:EventTrigger EventName="PreviewMouseDown">
-                                                <i:InvokeCommandAction Command="{Binding SetAsActiveOnClickCommand}"/>
-                                            </i:EventTrigger>
-                                        </i:Interaction.Triggers>
-                                        <usercontrols:DrawingViewPort.ContextMenu>
-                                            <cmds:ContextMenu>
-                                                <MenuItem Header="_Select All" cmds:ContextMenu.Command="PixiEditor.Selection.SelectAll" />
-                                                <MenuItem Header="_Deselect" cmds:ContextMenu.Command="PixiEditor.Selection.Clear" />
-                                                <Separator/>
-                                                <MenuItem Header="_Cut" cmds:ContextMenu.Command="PixiEditor.Clipboard.Cut" />
-                                                <MenuItem Header="_Copy" cmds:ContextMenu.Command="PixiEditor.Clipboard.Copy" />
-                                                <MenuItem Header="_Paste" cmds:ContextMenu.Command="PixiEditor.Clipboard.Paste" />
-                                            </cmds:ContextMenu>
-                                        </usercontrols:DrawingViewPort.ContextMenu>
-                                    </usercontrols:DrawingViewPort>
-                                </DataTemplate>
-                            </ui:DocumentsTemplateSelector.DocumentsViewTemplate>
-                        </ui:DocumentsTemplateSelector>
-                    </DockingManager.LayoutItemTemplateSelector>
-                    <avalondock:LayoutRoot x:Name="LayoutRoot">
-                        <LayoutPanel Orientation="Horizontal">
-                            <LayoutDocumentPane/>
-                            <LayoutAnchorablePaneGroup Orientation="Vertical" DockWidth="290">
+                                            <i:Interaction.Triggers>
+                                                <i:EventTrigger EventName="PreviewMouseDown">
+                                                    <i:InvokeCommandAction Command="{Binding SetAsActiveOnClickCommand}"/>
+                                                </i:EventTrigger>
+                                            </i:Interaction.Triggers>
+                                            <usercontrols:DrawingViewPort.ContextMenu>
+                                                <cmds:ContextMenu>
+                                                    <MenuItem Header="_Select All" cmds:ContextMenu.Command="PixiEditor.Selection.SelectAll" />
+                                                    <MenuItem Header="_Deselect" cmds:ContextMenu.Command="PixiEditor.Selection.Clear" />
+                                                    <Separator/>
+                                                    <MenuItem Header="_Cut" cmds:ContextMenu.Command="PixiEditor.Clipboard.Cut" />
+                                                    <MenuItem Header="_Copy" cmds:ContextMenu.Command="PixiEditor.Clipboard.Copy" />
+                                                    <MenuItem Header="_Paste" cmds:ContextMenu.Command="PixiEditor.Clipboard.Paste" />
+                                                </cmds:ContextMenu>
+                                            </usercontrols:DrawingViewPort.ContextMenu>
+                                        </usercontrols:DrawingViewPort>
+                                    </DataTemplate>
+                                </ui:DocumentsTemplateSelector.DocumentsViewTemplate>
+                            </ui:DocumentsTemplateSelector>
+                        </DockingManager.LayoutItemTemplateSelector>
+                        <avalondock:LayoutRoot x:Name="LayoutRoot">
+                            <LayoutPanel Orientation="Horizontal">
+                                <LayoutDocumentPane/>
+                                <LayoutAnchorablePaneGroup Orientation="Vertical" DockWidth="290">
 
-                                <LayoutAnchorablePane x:Name="colorPane">
-                                    <LayoutAnchorable ContentId="colorPicker" Title="Color Picker" CanHide="False"
+                                    <LayoutAnchorablePane x:Name="colorPane">
+                                        <LayoutAnchorable ContentId="colorPicker" Title="Color Picker" CanHide="False"
                                                              CanClose="False" CanAutoHide="False" x:Name="colorPickerPanel"
                                                              CanDockAsTabbedDocument="False" CanFloat="True">
-                                        <usercontrols:SmallColorPicker SelectedColor="{Binding ColorsSubViewModel.PrimaryColor, Mode=TwoWay, Converter={StaticResource SKColorToMediaColorConverter}}"
+                                            <usercontrols:SmallColorPicker SelectedColor="{Binding ColorsSubViewModel.PrimaryColor, Mode=TwoWay, Converter={StaticResource SKColorToMediaColorConverter}}"
                                                                          SecondaryColor="{Binding ColorsSubViewModel.SecondaryColor, Mode=TwoWay, Converter={StaticResource SKColorToMediaColorConverter}}" 
                                                                          Style="{StaticResource DefaultColorPickerStyle}" x:Name="mainColorPicker">
-                                            <i:Interaction.Behaviors>
-                                                <behaviours:GlobalShortcutFocusBehavior/>
-                                            </i:Interaction.Behaviors>
-                                        </usercontrols:SmallColorPicker>
-                                    </LayoutAnchorable>
-                                    <LayoutAnchorable ContentId="colorSliders" Title="Color Sliders" CanHide="False"
+                                                <i:Interaction.Behaviors>
+                                                    <behaviours:GlobalShortcutFocusBehavior/>
+                                                </i:Interaction.Behaviors>
+                                            </usercontrols:SmallColorPicker>
+                                        </LayoutAnchorable>
+                                        <LayoutAnchorable ContentId="colorSliders" Title="Color Sliders" CanHide="False"
                                                       CanClose="False" CanAutoHide="False" x:Name="colorSlidersPanel"
                                                       CanDockAsTabbedDocument="False" CanFloat="True">
-                                        <colorpicker:ColorSliders Style="{StaticResource DefaultColorPickerStyle}" 
+                                            <colorpicker:ColorSliders Style="{StaticResource DefaultColorPickerStyle}" 
                                                                   ColorState="{Binding ElementName=mainColorPicker, Path=ColorState, Delay=10, Mode=TwoWay}">
-                                            <i:Interaction.Behaviors>
-                                                <behaviours:GlobalShortcutFocusBehavior/>
-                                            </i:Interaction.Behaviors>
-                                        </colorpicker:ColorSliders>
-                                    </LayoutAnchorable>
-                                    <avalondock:LayoutAnchorable ContentId="swatches" Title="Swatches" CanHide="False"
+                                                <i:Interaction.Behaviors>
+                                                    <behaviours:GlobalShortcutFocusBehavior/>
+                                                </i:Interaction.Behaviors>
+                                            </colorpicker:ColorSliders>
+                                        </LayoutAnchorable>
+                                        <avalondock:LayoutAnchorable ContentId="swatches" Title="Swatches" CanHide="False"
                                                                  CanClose="False" CanAutoHide="False"
                                                                  CanDockAsTabbedDocument="False" CanFloat="True">
-                                        <usercontrols:SwatchesView
+                                            <usercontrols:SwatchesView
                                             SelectSwatchCommand="{cmds:Command PixiEditor.Colors.SelectColor, UseProvided=True}" RemoveSwatchCommand="{cmds:Command PixiEditor.Colors.RemoveSwatch, UseProvided=True}"
                                             Swatches="{Binding BitmapManager.ActiveDocument.Swatches}"/>
-                                    </avalondock:LayoutAnchorable>
-                                </LayoutAnchorablePane>
-                                <LayoutAnchorablePane>
-                                    <LayoutAnchorable ContentId="layers" Title="Layers" CanHide="False"
+                                        </avalondock:LayoutAnchorable>
+                                    </LayoutAnchorablePane>
+                                    <LayoutAnchorablePane>
+                                        <LayoutAnchorable ContentId="layers" Title="Layers" CanHide="False"
                                                          CanClose="False" CanAutoHide="False"
                                                          CanDockAsTabbedDocument="True" CanFloat="True">
-                                        <layerUserControls:LayersManager                                            
+                                            <layerUserControls:LayersManager                                            
                                             LayerCommandsViewModel="{Binding LayersSubViewModel}"
                                             OpacityInputEnabled="{Binding BitmapManager.ActiveDocument, 
                     Converter={converters:NotNullToBoolConverter}}">
-                                            <layerUserControls:LayersManager.LayerTreeRoot>
-                                                <MultiBinding Converter="{converters:LayersToStructuredLayersConverter}">
-                                                    <Binding Path="BitmapManager.ActiveDocument.Layers" />
-                                                    <Binding Path="BitmapManager.ActiveDocument.LayerStructure"/>
-                                                </MultiBinding>
-                                            </layerUserControls:LayersManager.LayerTreeRoot>
-                                        </layerUserControls:LayersManager>
-                                    </LayoutAnchorable>
-                                    <LayoutAnchorable x:Name="rawLayerAnchorable" ContentId="rawLayer" Title="Raw layers">
-                                        <layerUserControls:RawLayersViewer Layers="{Binding BitmapManager.ActiveDocument.Layers}"
+                                                <layerUserControls:LayersManager.LayerTreeRoot>
+                                                    <MultiBinding Converter="{converters:LayersToStructuredLayersConverter}">
+                                                        <Binding Path="BitmapManager.ActiveDocument.Layers" />
+                                                        <Binding Path="BitmapManager.ActiveDocument.LayerStructure"/>
+                                                    </MultiBinding>
+                                                </layerUserControls:LayersManager.LayerTreeRoot>
+                                            </layerUserControls:LayersManager>
+                                        </LayoutAnchorable>
+                                        <LayoutAnchorable x:Name="rawLayerAnchorable" ContentId="rawLayer" Title="Raw layers">
+                                            <layerUserControls:RawLayersViewer Layers="{Binding BitmapManager.ActiveDocument.Layers}"
                                                                       Structure="{Binding BitmapManager.ActiveDocument.LayerStructure}"/>
-                                    </LayoutAnchorable>
-                                </LayoutAnchorablePane>
-                                <LayoutAnchorablePane>
-                                    <LayoutAnchorable ContentId="navigation" Title="Navigation" 
+                                        </LayoutAnchorable>
+                                    </LayoutAnchorablePane>
+                                    <LayoutAnchorablePane>
+                                        <LayoutAnchorable ContentId="navigation" Title="Navigation" 
                                                       CanHide="True" CanAutoHide="False"
                                                       CanDockAsTabbedDocument="False" CanFloat="True">
-                                        <usercontrols:PreviewWindow 
+                                            <usercontrols:PreviewWindow 
                                             Document="{Binding BitmapManager.ActiveDocument}"
                                             PrimaryColor="{Binding ColorsSubViewModel.PrimaryColor, Mode=TwoWay, Converter={StaticResource SKColorToMediaColorConverter}}"/>
-                                    </LayoutAnchorable>
-                                </LayoutAnchorablePane>
-                            </LayoutAnchorablePaneGroup>
-                        </LayoutPanel>
-                    </avalondock:LayoutRoot>
-                </DockingManager>
+                                        </LayoutAnchorable>
+                                    </LayoutAnchorablePane>
+                                </LayoutAnchorablePaneGroup>
+                            </LayoutPanel>
+                        </avalondock:LayoutRoot>
+                    </DockingManager>
+                </Grid>
             </Grid>
-        </Grid>
 
-        <Border Grid.Row="2" Grid.Column="0"
+            <Border Grid.Row="2" Grid.Column="0"
                     Background="{StaticResource AccentColor}" Grid.RowSpan="2" CornerRadius="5,0,5,5">
-            <StackPanel Orientation="Vertical" Cursor="Arrow" >
+                <StackPanel Orientation="Vertical" Cursor="Arrow" >
 
-                <ItemsControl ItemsSource="{Binding ToolsSubViewModel.ToolSet}">
-                    <ItemsControl.ItemTemplate>
-                        <DataTemplate>
-                            <Button BorderBrush="White"                                
+                    <ItemsControl ItemsSource="{Binding ToolsSubViewModel.ToolSet}">
+                        <ItemsControl.ItemTemplate>
+                            <DataTemplate>
+                                <Button BorderBrush="White"                                
                                 BorderThickness="{Binding IsActive, Converter={StaticResource BoolToIntConverter}}"
                                 Style="{StaticResource ToolButtonStyle}"
                                 Command="{Binding Path=DataContext.ToolsSubViewModel.SelectToolCommand,
                                                   RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                 CommandParameter="{Binding}" ToolTip="{Binding Tooltip}">
-                                <Button.Background>
-                                    <ImageBrush ImageSource="{Binding ImagePath}" Stretch="Uniform" />
-                                </Button.Background>
-                                <Button.Resources>
-                                    <Style TargetType="Border">
-                                        <Setter Property="CornerRadius" Value="2.5"/>
-                                    </Style>
-                                </Button.Resources>
-                            </Button>
-                        </DataTemplate>
-                    </ItemsControl.ItemTemplate>
-                </ItemsControl>
-            </StackPanel>
-        </Border>
-
-        <Grid Grid.Row="3" Grid.Column="1">
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="*"/>
-                <ColumnDefinition Width="290"/>
-            </Grid.ColumnDefinitions>
-            <DockPanel>
-                <TextBlock Text="{Binding ActionDisplay}" Foreground="White" FontSize="15" Margin="10,0,0,0" VerticalAlignment="Center"/>
-                <StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
-                    <TextBlock Text="X:" Foreground="White" FontSize="16"/>
-                    <TextBlock Margin="4,0,10,0" Text="{Binding BitmapManager.ActiveDocument.MouseXOnCanvas, Converter={converters:DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
-                    <TextBlock Text="Y:" Foreground="White" FontSize="16"/>
-                    <TextBlock Margin="4,0,10,0" Text="{Binding BitmapManager.ActiveDocument.MouseYOnCanvas, Converter={converters:DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
+                                    <Button.Background>
+                                        <ImageBrush ImageSource="{Binding ImagePath}" Stretch="Uniform" />
+                                    </Button.Background>
+                                    <Button.Resources>
+                                        <Style TargetType="Border">
+                                            <Setter Property="CornerRadius" Value="2.5"/>
+                                        </Style>
+                                    </Button.Resources>
+                                </Button>
+                            </DataTemplate>
+                        </ItemsControl.ItemTemplate>
+                    </ItemsControl>
                 </StackPanel>
-            </DockPanel>
-            <StackPanel Margin="10,0,0,0" VerticalAlignment="Center" Grid.Row="3"
+            </Border>
+
+            <Grid Grid.Row="3" Grid.Column="1">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="*"/>
+                    <ColumnDefinition Width="290"/>
+                </Grid.ColumnDefinitions>
+                <DockPanel>
+                    <TextBlock Text="{Binding ActionDisplay}" Foreground="White" FontSize="15" Margin="10,0,0,0" VerticalAlignment="Center"/>
+                    <StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
+                        <TextBlock Text="X:" Foreground="White" FontSize="16"/>
+                        <TextBlock Margin="4,0,10,0" Text="{Binding BitmapManager.ActiveDocument.MouseXOnCanvas, Converter={converters:DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
+                        <TextBlock Text="Y:" Foreground="White" FontSize="16"/>
+                        <TextBlock Margin="4,0,10,0" Text="{Binding BitmapManager.ActiveDocument.MouseYOnCanvas, Converter={converters:DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
+                    </StackPanel>
+                </DockPanel>
+                <StackPanel Margin="10,0,0,0" VerticalAlignment="Center" Grid.Row="3"
                        Grid.Column="3" Orientation="Horizontal">
-                <Button Style="{StaticResource BaseDarkButton}" 
+                    <Button Style="{StaticResource BaseDarkButton}" 
                     Visibility="{Binding UpdateSubViewModel.UpdateReadyToInstall, Converter={StaticResource BoolToVisibilityConverter}, FallbackValue=Hidden}" FontSize="14" Height="20" 
                     Command="{cmds:Command PixiEditor.Restart}">Restart</Button>
-                <TextBlock VerticalAlignment="Center" Padding="10" HorizontalAlignment="Right"
+                    <TextBlock VerticalAlignment="Center" Padding="10" HorizontalAlignment="Right"
                        Foreground="White" FontSize="14"  Text="{Binding UpdateSubViewModel.VersionText}" />
-            </StackPanel>
+                </StackPanel>
+            </Grid>
         </Grid>
+        <usercontrols:CommandSearchControl HorizontalAlignment="Center" Height="700"/>
     </Grid>
 </Window>

+ 110 - 0
PixiEditor/Views/UserControls/CommandSearchControl.xaml

@@ -0,0 +1,110 @@
+<UserControl x:Class="PixiEditor.Views.UserControls.CommandSearchControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls"
+             xmlns:vm="clr-namespace:PixiEditor.ViewModels"
+             xmlns:behaves="clr-namespace:PixiEditor.Helpers.Behaviours"
+             xmlns:cmdssearch="clr-namespace:PixiEditor.Models.Commands.Search"
+             mc:Ignorable="d"
+             Foreground="White"
+             d:DesignHeight="450" d:DesignWidth="600">
+    <Grid DataContext="{DynamicResource viewModel}" x:Name="mainGrid">
+        <Grid.Resources>
+            <ResourceDictionary>
+                <vm:CommandSearchViewModel x:Key="viewModel"/>
+            </ResourceDictionary>
+        </Grid.Resources>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition Height="*"/>
+            <RowDefinition Height="Auto"/>
+        </Grid.RowDefinitions>
+
+        <TextBox Text="{Binding SearchTerm, UpdateSourceTrigger=PropertyChanged}" FontSize="18" Padding="5">
+            <TextBox.Style>
+                <Style TargetType="TextBox" BasedOn="{StaticResource DarkTextBoxStyle}">
+                    <Style.Resources>
+                        <Style TargetType="Border">
+                            <Setter Property="CornerRadius" Value="5,5,0,0"/>
+                        </Style>
+                    </Style.Resources>
+                </Style>
+            </TextBox.Style>
+        </TextBox>
+        <Border Grid.Row="1" BorderThickness="1,0,1,0" BorderBrush="{StaticResource BrighterAccentColor}"
+                Background="{StaticResource AccentColor}">
+            <ItemsControl ItemsSource="{Binding Commands}" MinWidth="400">
+                <ItemsControl.ItemTemplate>
+                    <DataTemplate DataType="cmdssearch:SearchTerm">
+                        <Button Padding="5" Height="40" BorderThickness="0" Background="Transparent"
+                                Command="{Binding ExecuteCommand}"
+                                CommandParameter="{Binding}"
+                                MouseMove="Button_MouseMove">
+                            <Button.Style>
+                                <Style TargetType="Button">
+                                    <Setter Property="Template">
+                                        <Setter.Value>
+                                            <ControlTemplate TargetType="Button">
+                                                <Border>
+                                                    <Border.Style>
+                                                        <Style TargetType="Border">
+                                                            <Style.Triggers>
+                                                                <Trigger Property="IsMouseOver" Value="False">
+                                                                    <Setter Property="Background" Value="Transparent"/>
+                                                                </Trigger>
+                                                                <Trigger Property="IsMouseOver" Value="True">
+                                                                    <Setter Property="Background" Value="{StaticResource BrighterAccentColor}"/>
+                                                                </Trigger>
+                                                                <DataTrigger Binding="{Binding CanExecute}" Value="False">
+                                                                    <Setter Property="Background" Value="Transparent"/>
+                                                                </DataTrigger>
+                                                            </Style.Triggers>
+                                                        </Style>
+                                                    </Border.Style>
+                                                    <ContentPresenter/>
+                                                </Border>
+                                            </ControlTemplate>
+                                        </Setter.Value>
+                                    </Setter>
+                                </Style>
+                            </Button.Style>
+                            <Button.Resources>
+                                <Style TargetType="TextBlock">
+                                    <Setter Property="FontSize" Value="16"/>
+                                    <Style.Triggers>
+                                        <DataTrigger Binding="{Binding CanExecute}" Value="True">
+                                            <Setter Property="Foreground" Value="White"/>
+                                        </DataTrigger>
+                                        <DataTrigger Binding="{Binding CanExecute}" Value="False">
+                                            <Setter Property="Foreground" Value="Gray"/>
+                                        </DataTrigger>
+                                    </Style.Triggers>
+                                </Style>
+                            </Button.Resources>
+                            <Grid VerticalAlignment="Center" x:Name="dp" Margin="5,0,10,0">
+                                <Grid.ColumnDefinitions>
+                                    <ColumnDefinition/>
+                                    <ColumnDefinition Width="Auto"/>
+                                </Grid.ColumnDefinitions>
+                                <StackPanel Orientation="Horizontal">
+                                    <Border Width="25" Margin="0,0,5,0" Padding="1">
+                                        <Image HorizontalAlignment="Center" Source="{Binding Icon}"/>
+                                    </Border>
+                                    <TextBlock VerticalAlignment="Center"
+                                               behaves:TextBlockExtensions.BindableInlines="{Binding TextBlockContent}"/>
+                                </StackPanel>
+                                <TextBlock Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Right" Text="{Binding Shortcut}"/>
+                            </Grid>
+                        </Button>
+                    </DataTemplate>
+                </ItemsControl.ItemTemplate>
+            </ItemsControl>
+        </Border>
+        <Border Grid.Row="2" BorderThickness="1" BorderBrush="{StaticResource BrighterAccentColor}"
+                CornerRadius="0,0,5,5" Background="{StaticResource AccentColor}">
+            <TextBlock Margin="5" FontSize="16" Text="{Binding SelectedResult.Description}"/>
+        </Border>
+    </Grid>
+</UserControl>

+ 26 - 0
PixiEditor/Views/UserControls/CommandSearchControl.xaml.cs

@@ -0,0 +1,26 @@
+using PixiEditor.Models.Commands.Search;
+using PixiEditor.ViewModels;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace PixiEditor.Views.UserControls
+{
+    /// <summary>
+    /// Interaction logic for CommandSearchControl.xaml
+    /// </summary>
+    public partial class CommandSearchControl : UserControl
+    {
+        public CommandSearchControl()
+        {
+            InitializeComponent();
+        }
+
+        private void Button_MouseMove(object sender, MouseEventArgs e)
+        {
+            var dataContext = mainGrid.DataContext as CommandSearchViewModel;
+            var searchResult = (sender as Button).DataContext as SearchResult;
+
+            dataContext.SelectedResult = searchResult;
+        }
+    }
+}