2
0
Эх сурвалжийг харах

All menu icons are now font icons

flabbet 1 жил өмнө
parent
commit
2353386214
19 өөрчлөгдсөн 109 нэмэгдсэн , 86 устгасан
  1. 1 1
      src/PixiEditor.AvaloniaUI/Models/Commands/Evaluators/IconEvaluator.cs
  2. 4 11
      src/PixiEditor.AvaloniaUI/Models/Commands/XAML/Menu.cs
  3. 7 6
      src/PixiEditor.AvaloniaUI/ViewModels/Document/DocumentManagerViewModel.cs
  4. 8 1
      src/PixiEditor.AvaloniaUI/ViewModels/Menu/MenuBuilders/FileExitMenuBuilder.cs
  5. 3 2
      src/PixiEditor.AvaloniaUI/ViewModels/Menu/MenuBuilders/SymmetryMenuBuilder.cs
  6. 2 1
      src/PixiEditor.AvaloniaUI/ViewModels/Menu/MenuBuilders/ToggleGridLinesMenuBuilder.cs
  7. 1 1
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ClipboardViewModel.cs
  8. 1 1
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ColorsViewModel.cs
  9. 2 2
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/FileViewModel.cs
  10. 8 5
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/LayersViewModel.cs
  11. 13 10
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/SelectionViewModel.cs
  12. 3 2
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/UndoViewModel.cs
  13. 7 3
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ViewOptionsViewModel.cs
  14. 4 11
      src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/WindowViewModel.cs
  15. 1 1
      src/PixiEditor.AvaloniaUI/ViewModels/Tools/Tools/LineToolViewModel.cs
  16. 3 3
      src/PixiEditor.AvaloniaUI/Views/Dialogs/AboutPopup.axaml
  17. 4 24
      src/PixiEditor.UI.Common/Fonts/PixiPerfectIcons.axaml.cs
  18. 34 0
      src/PixiEditor.UI.Common/Rendering/IconImage.cs
  19. 3 1
      src/PixiEditor/ViewModels/SubViewModels/Document/DocumentManagerViewModel.cs

+ 1 - 1
src/PixiEditor.AvaloniaUI/Models/Commands/Evaluators/IconEvaluator.cs

@@ -27,7 +27,7 @@ internal class IconEvaluator : Evaluator<IImage>
         {
             string symbolCode = command.Icon;
 
-            return PixiPerfectIcons.ToIcon(symbolCode, 64);
+            return PixiPerfectIcons.ToIcon(symbolCode);
         }
     }
 }

+ 4 - 11
src/PixiEditor.AvaloniaUI/Models/Commands/XAML/Menu.cs

@@ -1,6 +1,8 @@
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Layout;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
 using PixiEditor.AvaloniaUI.Helpers;
 using PixiEditor.AvaloniaUI.Models.Input;
 
@@ -42,18 +44,9 @@ internal class Menu : global::Avalonia.Controls.Menu
         {
             Source = command.GetIcon(),
             Width = IconDimensions, Height = IconDimensions,
-            Opacity = canExecute ? 1 : 0.75,
+            Stretch = Stretch.Uniform,
             VerticalAlignment = VerticalAlignment.Center,
-            HorizontalAlignment = HorizontalAlignment.Center
-        };
-
-        icon.PropertyChanged += async (sender, args) =>
-        {
-            bool canExecute = command.CanExecute();
-            if (args.Property.Name == nameof(icon.IsVisible))
-            {
-                icon.Opacity = canExecute ? 1 : 0.75;
-            }
+            HorizontalAlignment = HorizontalAlignment.Center,
         };
 
         item.Command = Command.GetICommand(command, false);

+ 7 - 6
src/PixiEditor.AvaloniaUI/ViewModels/Document/DocumentManagerViewModel.cs

@@ -62,8 +62,8 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>, IDocument
     [Evaluator.CanExecute("PixiEditor.HasDocument", nameof(ActiveDocument))]
     public bool DocumentNotNull() => ActiveDocument != null;
 
-    [Command.Basic("PixiEditor.Document.ClipCanvas", "CLIP_CANVAS", "CLIP_CANVAS", CanExecute = "PixiEditor.HasDocument", Icon = "Crop.png",
-        MenuItemPath = "IMAGE/CLIP_CANVAS", MenuItemOrder = 2)]
+    [Command.Basic("PixiEditor.Document.ClipCanvas", "CLIP_CANVAS", "CLIP_CANVAS", CanExecute = "PixiEditor.HasDocument",
+        Icon = PixiPerfectIcons.Crop, MenuItemPath = "IMAGE/CLIP_CANVAS", MenuItemOrder = 2)]
     public void ClipCanvas() => ActiveDocument?.Operations.ClipCanvas();
 
     [Command.Basic("PixiEditor.Document.FlipImageHorizontal", FlipType.Horizontal, "FLIP_IMG_HORIZONTALLY", "FLIP_IMG_HORIZONTALLY", CanExecute = "PixiEditor.HasDocument",
@@ -153,7 +153,8 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>, IDocument
         ActiveDocument.EventInlet.OnSymmetryDragEnded(dir);
     }
 
-    [Command.Basic("PixiEditor.Document.DeletePixels", "DELETE_PIXELS", "DELETE_PIXELS_DESCRIPTIVE", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.Delete, Icon = "Tools/EraserImage.png",
+    [Command.Basic("PixiEditor.Document.DeletePixels", "DELETE_PIXELS", "DELETE_PIXELS_DESCRIPTIVE", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.Delete, 
+        Icon = PixiPerfectIcons.Eraser,
         MenuItemPath = "EDIT/DELETE_SELECTED_PIXELS", MenuItemOrder = 6)]
     public void DeletePixels()
     {
@@ -162,9 +163,9 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>, IDocument
 
 
     [Command.Basic("PixiEditor.Document.ResizeDocument", false, "RESIZE_DOCUMENT", "RESIZE_DOCUMENT", CanExecute = "PixiEditor.HasDocument", Key = Key.I, Modifiers = KeyModifiers.Control | KeyModifiers.Shift,
-        MenuItemPath = "IMAGE/RESIZE_IMAGE", MenuItemOrder = 0)]
+        Icon = PixiPerfectIcons.Resize, MenuItemPath = "IMAGE/RESIZE_IMAGE", MenuItemOrder = 0)]
     [Command.Basic("PixiEditor.Document.ResizeCanvas", true, "RESIZE_CANVAS", "RESIZE_CANVAS", CanExecute = "PixiEditor.HasDocument", Key = Key.C, Modifiers = KeyModifiers.Control | KeyModifiers.Shift,
-        MenuItemPath = "IMAGE/RESIZE_CANVAS", MenuItemOrder = 1)]
+        Icon = PixiPerfectIcons.CanvasResize, MenuItemPath = "IMAGE/RESIZE_CANVAS", MenuItemOrder = 1)]
     public async Task OpenResizePopup(bool canvas)
     {
         DocumentViewModel? doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
@@ -190,7 +191,7 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>, IDocument
     }
 
     [Command.Basic("PixiEditor.Document.CenterContent", "CENTER_CONTENT", "CENTER_CONTENT", CanExecute = "PixiEditor.HasDocument",
-        MenuItemPath = "IMAGE/CENTER_CONTENT", MenuItemOrder = 3)]
+        Icon = PixiPerfectIcons.Center, MenuItemPath = "IMAGE/CENTER_CONTENT", MenuItemOrder = 3)]
     public void CenterContent()
     {
         if(ActiveDocument?.SelectedStructureMember == null)

+ 8 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Menu/MenuBuilders/FileExitMenuBuilder.cs

@@ -3,6 +3,7 @@ using Avalonia.Controls;
 using PixiEditor.AvaloniaUI.Views;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Extensions.UI;
+using PixiEditor.UI.Common.Fonts;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.Menu.MenuBuilders;
 
@@ -15,7 +16,13 @@ internal class FileExitMenuBuilder : MenuItemBuilder
             var exitMenuItem = new MenuItem
             {
                 Command = SystemCommands.CloseWindowCommand,
-                CommandParameter = MainWindow.Current
+                CommandParameter = MainWindow.Current,
+                Icon = new Image()
+                {
+                    Source = PixiPerfectIcons.ToIcon(PixiPerfectIcons.Exit),
+                    Width = Models.Commands.XAML.Menu.IconDimensions,
+                    Height = Models.Commands.XAML.Menu.IconDimensions
+                }
             };
 
             Translator.SetKey(exitMenuItem, "EXIT");

+ 3 - 2
src/PixiEditor.AvaloniaUI/ViewModels/Menu/MenuBuilders/SymmetryMenuBuilder.cs

@@ -6,6 +6,7 @@ using Avalonia.Input;
 using PixiEditor.AvaloniaUI.Helpers.Converters;
 using PixiEditor.AvaloniaUI.Views.Input;
 using PixiEditor.Extensions.UI;
+using PixiEditor.UI.Common.Fonts;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.Menu.MenuBuilders;
 
@@ -21,7 +22,7 @@ internal class SymmetryMenuBuilder : MenuItemBuilder
             Translator.SetKey(horizontalSymmetryItem, "HORIZONTAL_LINE_SYMMETRY");
             horizontalSymmetryItem.Icon = new Image()
             {
-                Source = ImagePathToBitmapConverter.LoadBitmapFromRelativePath("/Images/SymmetryHorizontal.png"),
+                Source = PixiPerfectIcons.ToIcon(PixiPerfectIcons.XSymmetry),
                 Width = Models.Commands.XAML.Menu.IconDimensions,
                 Height = Models.Commands.XAML.Menu.IconDimensions
             };
@@ -33,7 +34,7 @@ internal class SymmetryMenuBuilder : MenuItemBuilder
             Translator.SetKey(verticalSymmetryItem, "VERTICAL_LINE_SYMMETRY");
             verticalSymmetryItem.Icon = new Image()
             {
-                Source = ImagePathToBitmapConverter.LoadBitmapFromRelativePath("/Images/SymmetryVertical.png"),
+                Source = PixiPerfectIcons.ToIcon(PixiPerfectIcons.YSymmetry),
                 Width = Models.Commands.XAML.Menu.IconDimensions,
                 Height = Models.Commands.XAML.Menu.IconDimensions
             };

+ 2 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Menu/MenuBuilders/ToggleGridLinesMenuBuilder.cs

@@ -6,6 +6,7 @@ using Avalonia.Input;
 using PixiEditor.AvaloniaUI.Helpers.Converters;
 using PixiEditor.AvaloniaUI.Views.Input;
 using PixiEditor.Extensions.UI;
+using PixiEditor.UI.Common.Fonts;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.Menu.MenuBuilders;
 
@@ -20,7 +21,7 @@ internal class ToggleGridLinesMenuBuilder : MenuItemBuilder
             Translator.SetKey(gridLinesItem, "TOGGLE_GRIDLINES");
             gridLinesItem.Icon = new Image()
             {
-                Source = ImagePathToBitmapConverter.LoadBitmapFromRelativePath("/Images/Commands/PixiEditor/View/ToggleGrid.png"),
+                Source = PixiPerfectIcons.ToIcon(PixiPerfectIcons.Grid),
                 Width = Models.Commands.XAML.Menu.IconDimensions,
                 Height = Models.Commands.XAML.Menu.IconDimensions
             };

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ClipboardViewModel.cs

@@ -32,7 +32,7 @@ internal class ClipboardViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Clipboard.Cut", "CUT", "CUT_DESCRIPTIVE", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.X, Modifiers = KeyModifiers.Control,
-        MenuItemPath = "EDIT/CUT", MenuItemOrder = 2, Icon = PixiPerfectIcons.Cut)]
+        MenuItemPath = "EDIT/CUT", MenuItemOrder = 2, Icon = PixiPerfectIcons.Scissors)]
     public async Task Cut()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ColorsViewModel.cs

@@ -162,7 +162,7 @@ internal class ColorsViewModel : SubViewModel<ViewModelMain>, IColorsHandler
     }
 
     [Command.Basic("PixiEditor.Colors.OpenPaletteBrowser", "OPEN_PALETTE_BROWSER", "OPEN_PALETTE_BROWSER", CanExecute = "PixiEditor.HasDocument", 
-        Icon = PixiPerfectIcons.Database)]
+        Icon = PixiPerfectIcons.Database, MenuItemPath = "VIEW/OPEN_PALETTE_BROWSER", MenuItemOrder = 3)]
     public void OpenPalettesBrowser() 
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;

+ 2 - 2
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/FileViewModel.cs

@@ -132,7 +132,7 @@ internal class FileViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.File.Open", "OPEN", "OPEN_FILE", Key = Key.O, Modifiers = KeyModifiers.Control,
-        MenuItemPath = "FILE/OPEN_FILE", MenuItemOrder = 1)]
+        MenuItemPath = "FILE/OPEN_FILE", MenuItemOrder = 1, Icon = PixiPerfectIcons.FileText)]
     public async Task OpenFromOpenFileDialog()
     {
         var filter = SupportedFilesHelper.BuildOpenFilter();
@@ -353,7 +353,7 @@ internal class FileViewModel : SubViewModel<ViewModelMain>
     /// </summary>
     /// <param name="parameter">CommandProperty.</param>
     [Command.Basic("PixiEditor.File.Export", "EXPORT", "EXPORT_IMAGE", CanExecute = "PixiEditor.HasDocument", Key = Key.E, Modifiers = KeyModifiers.Control,
-        MenuItemPath = "FILE/EXPORT_IMG", MenuItemOrder = 5)]
+        MenuItemPath = "FILE/EXPORT_IMG", MenuItemOrder = 5, Icon = PixiPerfectIcons.Image)]
     public async Task ExportFile()
     {
         try

+ 8 - 5
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/LayersViewModel.cs

@@ -23,6 +23,7 @@ using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Extensions.Exceptions;
 using PixiEditor.Numerics;
+using PixiEditor.UI.Common.Fonts;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 #nullable enable
@@ -53,7 +54,8 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
         return true;
     }
 
-    [Command.Basic("PixiEditor.Layer.DeleteSelected", "LAYER_DELETE_SELECTED", "LAYER_DELETE_SELECTED_DESCRIPTIVE", CanExecute = "PixiEditor.Layer.CanDeleteSelected", Icon = "Trash.png")]
+    [Command.Basic("PixiEditor.Layer.DeleteSelected", "LAYER_DELETE_SELECTED", "LAYER_DELETE_SELECTED_DESCRIPTIVE", CanExecute = "PixiEditor.Layer.CanDeleteSelected", 
+        Icon = PixiPerfectIcons.Trash)]
     public void DeleteSelected()
     {
         var member = Owner.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
@@ -96,7 +98,8 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
         return members;
     }
 
-    [Command.Basic("PixiEditor.Layer.DeleteAllSelected", "LAYER_DELETE_ALL_SELECTED", "LAYER_DELETE_ALL_SELECTED_DESCRIPTIVE", CanExecute = "PixiEditor.Layer.HasSelectedMembers", Icon = "Trash.png")]
+    [Command.Basic("PixiEditor.Layer.DeleteAllSelected", "LAYER_DELETE_ALL_SELECTED", "LAYER_DELETE_ALL_SELECTED_DESCRIPTIVE", CanExecute = "PixiEditor.Layer.HasSelectedMembers", 
+        Icon = PixiPerfectIcons.Trash)]
     public void DeleteAllSelected()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
@@ -169,7 +172,7 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Layer.DuplicateSelectedLayer", "DUPLICATE_SELECTED_LAYER", "DUPLICATE_SELECTED_LAYER", CanExecute = "PixiEditor.Layer.SelectedMemberIsLayer",
-        MenuItemPath = "EDIT/DUPLICATE", MenuItemOrder = 5)]
+        Icon = PixiPerfectIcons.DuplicateFile, MenuItemPath = "EDIT/DUPLICATE", MenuItemOrder = 5)]
     public void DuplicateLayer()
     {
         var member = Owner.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
@@ -244,7 +247,7 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
         doc!.Operations.CreateMask(member);
     }
 
-    [Command.Basic("PixiEditor.Layer.DeleteMask", "DELETE_MASK", "DELETE_MASK", CanExecute = "PixiEditor.Layer.ActiveLayerHasMask", Icon = "Trash.png")]
+    [Command.Basic("PixiEditor.Layer.DeleteMask", "DELETE_MASK", "DELETE_MASK", CanExecute = "PixiEditor.Layer.ActiveLayerHasMask", Icon = "PixiPerfectIcons.Trash")]
     public void DeleteMask()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
@@ -389,7 +392,7 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
         return null;
     }
 
-    [Command.Basic("PixiEditor.Layer.DeleteReferenceLayer", "DELETE_REFERENCE_LAYER", "DELETE_REFERENCE_LAYER", CanExecute = "PixiEditor.Layer.ReferenceLayerExists", Icon = "Trash.png")]
+    [Command.Basic("PixiEditor.Layer.DeleteReferenceLayer", "DELETE_REFERENCE_LAYER", "DELETE_REFERENCE_LAYER", CanExecute = "PixiEditor.Layer.ReferenceLayerExists", Icon = "PixiPerfectIcons.Trash")]
     public void DeleteReferenceLayer()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;

+ 13 - 10
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/SelectionViewModel.cs

@@ -1,9 +1,11 @@
-using Avalonia.Input;
+using System.Drawing;
+using Avalonia.Input;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Evaluators;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Numerics;
+using PixiEditor.UI.Common.Fonts;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 
@@ -16,7 +18,7 @@ internal class SelectionViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Selection.SelectAll", "SELECT_ALL", "SELECT_ALL_DESCRIPTIVE", CanExecute = "PixiEditor.HasDocument", Key = Key.A, Modifiers = KeyModifiers.Control,
-        MenuItemPath = "SELECT/SELECT_ALL", MenuItemOrder = 8)]
+        MenuItemPath = "SELECT/SELECT_ALL", MenuItemOrder = 8, Icon = PixiPerfectIcons.SelectAll)]
     public void SelectAll()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
@@ -26,7 +28,7 @@ internal class SelectionViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Selection.Clear", "CLEAR_SELECTION", "CLEAR_SELECTION", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.D, Modifiers = KeyModifiers.Control,
-        MenuItemPath = "SELECT/DESELECT", MenuItemOrder = 9)]
+        MenuItemPath = "SELECT/DESELECT", MenuItemOrder = 9, Icon = PixiPerfectIcons.Deselect)]
     public void ClearSelection()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
@@ -36,7 +38,7 @@ internal class SelectionViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Selection.InvertSelection", "INVERT_SELECTION", "INVERT_SELECTION_DESCRIPTIVE", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.I, Modifiers = KeyModifiers.Control,
-        MenuItemPath = "SELECT/INVERT", MenuItemOrder = 10)]
+        MenuItemPath = "SELECT/INVERT", MenuItemOrder = 10, Icon = PixiPerfectIcons.Invert)]
     public void InvertSelection()
     {
         Owner.DocumentManagerSubViewModel.ActiveDocument?.Operations.InvertSelection();
@@ -54,7 +56,8 @@ internal class SelectionViewModel : SubViewModel<ViewModelMain>
         return SelectionIsNotEmpty() && (Owner.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember?.HasMaskBindable ?? false);
     }
 
-    [Command.Basic("PixiEditor.Selection.TransformArea", "TRANSFORM_SELECTED_AREA", "TRANSFORM_SELECTED_AREA", CanExecute = "PixiEditor.Selection.IsNotEmpty", Key = Key.T, Modifiers = KeyModifiers.Control)]
+    [Command.Basic("PixiEditor.Selection.TransformArea", "TRANSFORM_SELECTED_AREA", "TRANSFORM_SELECTED_AREA", CanExecute = "PixiEditor.Selection.IsNotEmpty", 
+        Key = Key.T, Modifiers = KeyModifiers.Control)]
     public void TransformSelectedArea()
     {
         Owner.DocumentManagerSubViewModel.ActiveDocument?.Operations.TransformSelectedArea(false);
@@ -71,13 +74,13 @@ internal class SelectionViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Selection.NewToMask", SelectionMode.New, "MASK_FROM_SELECTION", "MASK_FROM_SELECTION_DESCRIPTIVE", CanExecute = "PixiEditor.Selection.IsNotEmpty",
-        MenuItemPath = "SELECT/SELECTION_TO_MASK/TO_NEW_MASK", MenuItemOrder = 12)]
+        MenuItemPath = "SELECT/SELECTION_TO_MASK/TO_NEW_MASK", MenuItemOrder = 12, Icon = PixiPerfectIcons.NewMask)]
     [Command.Basic("PixiEditor.Selection.AddToMask", SelectionMode.Add, "ADD_SELECTION_TO_MASK", "ADD_SELECTION_TO_MASK", CanExecute = "PixiEditor.Selection.IsNotEmpty",
-        MenuItemPath = "SELECT/SELECTION_TO_MASK/ADD_TO_MASK", MenuItemOrder = 13)]
+        MenuItemPath = "SELECT/SELECTION_TO_MASK/ADD_TO_MASK", MenuItemOrder = 13, Icon = PixiPerfectIcons.AddToMask)]
     [Command.Basic("PixiEditor.Selection.SubtractFromMask", SelectionMode.Subtract, "SUBTRACT_SELECTION_FROM_MASK", "SUBTRACT_SELECTION_FROM_MASK", CanExecute = "PixiEditor.Selection.IsNotEmptyAndHasMask",
-        MenuItemPath = "SELECT/SELECTION_TO_MASK/SUBTRACT_FROM_MASK", MenuItemOrder = 14)]
+        MenuItemPath = "SELECT/SELECTION_TO_MASK/SUBTRACT_FROM_MASK", MenuItemOrder = 14, Icon = PixiPerfectIcons.Subtract)]
     [Command.Basic("PixiEditor.Selection.IntersectSelectionMask", SelectionMode.Intersect, "INTERSECT_SELECTION_MASK", "INTERSECT_SELECTION_MASK", CanExecute = "PixiEditor.Selection.IsNotEmptyAndHasMask",
-        MenuItemPath = "SELECT/SELECTION_TO_MASK/INTERSECT_WITH_MASK", MenuItemOrder = 15)]
+        MenuItemPath = "SELECT/SELECTION_TO_MASK/INTERSECT_WITH_MASK", MenuItemOrder = 15, Icon = PixiPerfectIcons.Intersect)]
     [Command.Filter("PixiEditor.Selection.ToMaskMenu", "SELECTION_TO_MASK", "SELECTION_TO_MASK", Key = Key.M, Modifiers = KeyModifiers.Control)]
     public void SelectionToMask(SelectionMode mode)
     {
@@ -85,7 +88,7 @@ internal class SelectionViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Selection.CropToSelection", "CROP_TO_SELECTION", "CROP_TO_SELECTION_DESCRIPTIVE", CanExecute = "PixiEditor.Selection.IsNotEmpty",
-        MenuItemPath = "SELECT/CROP_TO_SELECTION", MenuItemOrder = 11)]
+        MenuItemPath = "SELECT/CROP_TO_SELECTION", MenuItemOrder = 11, Icon = PixiPerfectIcons.CropToSelection)]
     public void CropToSelection()
     {
         var document = Owner.DocumentManagerSubViewModel.ActiveDocument;

+ 3 - 2
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/UndoViewModel.cs

@@ -1,6 +1,7 @@
 using Avalonia.Input;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Evaluators;
+using PixiEditor.UI.Common.Fonts;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 
@@ -16,7 +17,7 @@ internal class UndoViewModel : SubViewModel<ViewModelMain>
     ///     Redo last action.
     /// </summary>
     [Command.Basic("PixiEditor.Undo.Redo", "REDO", "REDO_DESCRIPTIVE", CanExecute = "PixiEditor.Undo.CanRedo", Key = Key.Y, Modifiers = KeyModifiers.Control,
-        Icon = "Redo.png", MenuItemPath = "EDIT/REDO", MenuItemOrder = 1)]
+        Icon = PixiPerfectIcons.Redo, MenuItemPath = "EDIT/REDO", MenuItemOrder = 1)]
     public void Redo()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
@@ -29,7 +30,7 @@ internal class UndoViewModel : SubViewModel<ViewModelMain>
     ///     Undo last action.
     /// </summary>
     [Command.Basic("PixiEditor.Undo.Undo", "UNDO", "UNDO_DESCRIPTIVE", CanExecute = "PixiEditor.Undo.CanUndo", Key = Key.Z, Modifiers = KeyModifiers.Control,
-        Icon = "Undo.png", MenuItemPath = "EDIT/UNDO", MenuItemOrder = 0)]
+        Icon = PixiPerfectIcons.Undo, MenuItemPath = "EDIT/UNDO", MenuItemOrder = 0)]
     public void Undo()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;

+ 7 - 3
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ViewOptionsViewModel.cs

@@ -1,5 +1,6 @@
 using Avalonia.Input;
 using PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands;
+using PixiEditor.UI.Common.Fonts;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 #nullable enable
@@ -18,14 +19,17 @@ internal class ViewOptionsViewModel : SubViewModel<ViewModelMain>
     {
     }
 
-    [Command.Basic("PixiEditor.View.ToggleGrid", "TOGGLE_GRIDLINES", "TOGGLE_GRIDLINES", Key = Key.OemTilde, Modifiers = KeyModifiers.Control)]
+    [Command.Basic("PixiEditor.View.ToggleGrid", "TOGGLE_GRIDLINES", "TOGGLE_GRIDLINES", Key = Key.OemTilde, Modifiers = KeyModifiers.Control,
+        Icon = PixiPerfectIcons.Grid)]
     public void ToggleGridLines()
     {
         GridLinesEnabled = !GridLinesEnabled;
     }
 
-    [Command.Basic("PixiEditor.View.ZoomIn", 1, "ZOOM_IN", "ZOOM_IN", CanExecute = "PixiEditor.HasDocument", Key = Key.OemPlus)]
-    [Command.Basic("PixiEditor.View.Zoomout", -1, "ZOOM_OUT", "ZOOM_OUT", CanExecute = "PixiEditor.HasDocument", Key = Key.OemMinus)]
+    [Command.Basic("PixiEditor.View.ZoomIn", 1, "ZOOM_IN", "ZOOM_IN", CanExecute = "PixiEditor.HasDocument", Key = Key.OemPlus,
+        Icon = PixiPerfectIcons.ZoomIn)]
+    [Command.Basic("PixiEditor.View.Zoomout", -1, "ZOOM_OUT", "ZOOM_OUT", CanExecute = "PixiEditor.HasDocument", Key = Key.OemMinus,
+        Icon = PixiPerfectIcons.ZoomOut)]
     public void ZoomViewport(double zoom)
     {
         ViewportWindowViewModel? viewport = Owner.WindowSubViewModel.ActiveWindow as ViewportWindowViewModel;

+ 4 - 11
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/WindowViewModel.cs

@@ -153,7 +153,7 @@ internal class WindowViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Window.OpenSettingsWindow", "OPEN_SETTINGS", "OPEN_SETTINGS_DESCRIPTIVE", Key = Key.OemComma, Modifiers = KeyModifiers.Control,
-        MenuItemPath = "EDIT/SETTINGS", MenuItemOrder = 16)]
+        MenuItemPath = "EDIT/SETTINGS", MenuItemOrder = 16, Icon = PixiPerfectIcons.Settings)]
     public static void OpenSettingsWindow(int page)
     {
         if (page < 0)
@@ -166,29 +166,22 @@ internal class WindowViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Window.OpenStartupWindow", "OPEN_STARTUP_WINDOW", "OPEN_STARTUP_WINDOW",
-        MenuItemPath = "VIEW/OPEN_STARTUP_WINDOW", MenuItemOrder = 1)]
+        Icon = PixiPerfectIcons.Home, MenuItemPath = "VIEW/OPEN_STARTUP_WINDOW", MenuItemOrder = 1)]
     public void OpenHelloThereWindow()
     {
         new HelloTherePopup(Owner.FileSubViewModel).Show(MainWindow.Current);
     }
 
     [Command.Basic("PixiEditor.Window.OpenShortcutWindow", "OPEN_SHORTCUT_WINDOW", "OPEN_SHORTCUT_WINDOW", Key = Key.F1,
-        MenuItemPath = "VIEW/OPEN_SHORTCUT_WINDOW", MenuItemOrder = 2)]
+        Icon = PixiPerfectIcons.Book, MenuItemPath = "VIEW/OPEN_SHORTCUT_WINDOW", MenuItemOrder = 2)]
     public void ShowShortcutWindow()
     {
         ShortcutsPopup.Show();
         ShortcutsPopup.Activate();
     }
-
-    [Command.Basic("PixiEditor.Window.OpenPalettesBrowserWindow", "OPEN_PALETTE_BROWSER", "OPEN_PALETTE_BROWSER",
-        Icon = "Database.png", MenuItemPath = "VIEW/OPEN_PALETTE_BROWSER", MenuItemOrder = 3)]
-    public void ShowPalettesBrowserWindow()
-    {
-        PalettesBrowser.Open();
-    }
         
     [Command.Basic("PixiEditor.Window.OpenAboutWindow", "OPEN_ABOUT_WINDOW", "OPEN_ABOUT_WINDOW",
-        MenuItemPath = "HELP/ABOUT", MenuItemOrder = 5)]
+        Icon = PixiPerfectIcons.Info, MenuItemPath = "HELP/ABOUT", MenuItemOrder = 5)]
     public void OpenAboutWindow()
     {
         new AboutPopup().Show();

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Tools/Tools/LineToolViewModel.cs

@@ -24,7 +24,7 @@ internal class LineToolViewModel : ShapeTool, ILineToolHandler
     public override string ToolNameLocalizationKey => "LINE_TOOL";
     public override LocalizedString Tooltip => new LocalizedString("LINE_TOOL_TOOLTIP", Shortcut);
 
-    public override string Icon => PixiPerfectIcons.Eraser;
+    public override string Icon => PixiPerfectIcons.Line;
 
     [Settings.Inherited]
     public int ToolSize => GetValue<int>();

+ 3 - 3
src/PixiEditor.AvaloniaUI/Views/Dialogs/AboutPopup.axaml

@@ -11,12 +11,12 @@
         x:Class="PixiEditor.AvaloniaUI.Views.Dialogs.AboutPopup"
         Name="aboutPopup"
         CanResize="True"
-        Width="440" Height="510"
-        MaxWidth="440" MaxHeight="510"
+        Width="440" Height="520"
+        MaxWidth="440" MaxHeight="520"
         Title="ABOUT">
     <StackPanel DataContext="{Binding ElementName=aboutPopup}" Orientation="Vertical" DockPanel.Dock="Bottom" Margin="10">
             <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top">
-                <Image Source="../../Images/PixiEditorLogo.png" Height="40" VerticalAlignment="Center"/>
+                <Svg Path="../../Images/PixiEditorLogo.svg" Height="40" VerticalAlignment="Center"/>
                 <TextBlock FontSize="40" FontWeight="SemiBold" Foreground="{DynamicResource ThemeForegroundBrush}" VerticalAlignment="Center" Margin="10,0,0,0">PixiEditor</TextBlock>
             </StackPanel>
             <TextBlock Foreground="{DynamicResource ThemeForegroundBrush}" HorizontalAlignment="Center" FontSize="20" FontWeight="Medium" ui:Translator.LocalizedString="{Binding VersionText}"/>

+ 4 - 24
src/PixiEditor.UI.Common/Fonts/PixiPerfectIcons.axaml.cs

@@ -1,6 +1,8 @@
 using Avalonia;
 using Avalonia.Controls;
+using Avalonia.Layout;
 using Avalonia.Media;
+using PixiEditor.UI.Common.Rendering;
 
 namespace PixiEditor.UI.Common.Fonts;
 
@@ -108,36 +110,14 @@ public static class PixiPerfectIcons
     public const string YSymmetry = "\uE960";
     public const string ZoomIn = "\uE961";
     public const string ZoomOut = "\uE962";
-    public const string Cut = "\u25a1"; // TODO: Create a cut icon
     public const string PasteReferenceLayer = "\u25a1"; // TODO: Create a paste reference layer icon
     public const string PasteAsNewLayer = "\u25a1"; // TODO: Create a paste as new layer icon
     public const string CopyAdd = "\u25a1"; // TODO: Create a copy add icon
 
-    public static IImage ToIcon(string unicode, double size = 64)
+    public static IImage ToIcon(string unicode, double size = 18)
     {
         if(string.IsNullOrEmpty(unicode)) return null;
 
-        var textBlock = new TextBlock
-        {
-            FontFamily = pixiPerfectFontFamily,
-            Foreground = Brushes.White,
-            Text = unicode,
-            FontSize = size,
-        };
-
-        var brush = new VisualBrush
-        {
-            Visual = textBlock,
-            Stretch = Stretch.Uniform,
-        };
-
-        var drawing = new GeometryDrawing
-        {
-            Brush = brush,
-            Geometry = new RectangleGeometry(
-                new Rect(0, 0, 64, 64)),
-        };
-
-        return new DrawingImage(drawing);
+        return new IconImage(unicode, pixiPerfectFontFamily, size, Colors.White);
     }
 }

+ 34 - 0
src/PixiEditor.UI.Common/Rendering/IconImage.cs

@@ -0,0 +1,34 @@
+using System.Globalization;
+using Avalonia;
+using Avalonia.Media;
+
+namespace PixiEditor.UI.Common.Rendering;
+
+public class IconImage : IImage
+{
+    public string Icon { get; }
+    public FontFamily FontFamily { get; }
+    public double FontSize { get; }
+    
+    public SolidColorBrush Foreground { get; }
+    public Size Size { get; }
+    
+    private Typeface _typeface;
+    
+    public IconImage(string icon, FontFamily fontFamily, double fontSize, Color foreground)
+    {
+        Icon = icon;
+        FontFamily = fontFamily;
+        FontSize = fontSize;
+        Foreground = new SolidColorBrush(foreground);
+        _typeface = new Typeface(FontFamily);
+        Size = new Size(FontSize, FontSize);
+    }
+    
+    public void Draw(DrawingContext context, Rect sourceRect, Rect destRect)
+    {
+        context.DrawText(
+            new FormattedText(Icon, CultureInfo.InvariantCulture, FlowDirection.LeftToRight, _typeface, FontSize, Foreground),
+            destRect.TopLeft);
+    }
+}

+ 3 - 1
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentManagerViewModel.cs

@@ -1,4 +1,5 @@
 using System.Collections.ObjectModel;
+using System.Drawing;
 using System.Windows.Input;
 using ChunkyImageLib.Operations;
 using PixiEditor.ChangeableDocument.Enums;
@@ -49,7 +50,8 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>
     [Evaluator.CanExecute("PixiEditor.HasDocument")]
     public bool DocumentNotNull() => ActiveDocument != null;
 
-    [Command.Basic("PixiEditor.Document.ClipCanvas", "CLIP_CANVAS", "CLIP_CANVAS", CanExecute = "PixiEditor.HasDocument", IconPath = "crop.png")]
+    [Command.Basic("PixiEditor.Document.ClipCanvas", "CLIP_CANVAS", "CLIP_CANVAS", CanExecute = "PixiEditor.HasDocument", 
+        IconPath = "crop.png")]
     public void ClipCanvas() => ActiveDocument?.Operations.ClipCanvas();
 
     [Command.Basic("PixiEditor.Document.FlipImageHorizontal", FlipType.Horizontal, "FLIP_IMG_HORIZONTALLY", "FLIP_IMG_HORIZONTALLY", CanExecute = "PixiEditor.HasDocument")]