Browse Source

Create new layer if incompatible

flabbet 11 months ago
parent
commit
16e92a7fe2
32 changed files with 246 additions and 96 deletions
  1. 11 13
      src/PixiEditor.ChangeableDocument/Changes/Structure/CreateStructureMember_Change.cs
  2. 3 3
      src/PixiEditor/Models/DocumentModels/ChangeExecutionController.cs
  3. 31 5
      src/PixiEditor/Models/DocumentModels/DocumentStructureHelper.cs
  4. 9 0
      src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs
  5. 20 1
      src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs
  6. 9 0
      src/PixiEditor/Models/DocumentModels/Public/InvokeAction_PassthroughAction.cs
  7. 7 3
      src/PixiEditor/Models/Handlers/IToolHandler.cs
  8. 1 1
      src/PixiEditor/ViewModels/Document/DocumentManagerViewModel.cs
  9. 2 2
      src/PixiEditor/ViewModels/Document/DocumentViewModel.cs
  10. 5 5
      src/PixiEditor/ViewModels/SubViewModels/IoViewModel.cs
  11. 9 0
      src/PixiEditor/ViewModels/SubViewModels/LayersViewModel.cs
  12. 26 6
      src/PixiEditor/ViewModels/SubViewModels/ToolsViewModel.cs
  13. 39 28
      src/PixiEditor/ViewModels/Tools/ToolViewModel.cs
  14. 4 1
      src/PixiEditor/ViewModels/Tools/Tools/BrightnessToolViewModel.cs
  15. 2 1
      src/PixiEditor/ViewModels/Tools/Tools/ColorPickerToolViewModel.cs
  16. 4 1
      src/PixiEditor/ViewModels/Tools/Tools/EraserToolViewModel.cs
  17. 4 1
      src/PixiEditor/ViewModels/Tools/Tools/FloodFillToolViewModel.cs
  18. 3 1
      src/PixiEditor/ViewModels/Tools/Tools/LassoToolViewModel.cs
  19. 4 2
      src/PixiEditor/ViewModels/Tools/Tools/MagicWandToolViewModel.cs
  20. 2 1
      src/PixiEditor/ViewModels/Tools/Tools/MoveToolViewModel.cs
  21. 2 1
      src/PixiEditor/ViewModels/Tools/Tools/MoveViewportToolViewModel.cs
  22. 5 4
      src/PixiEditor/ViewModels/Tools/Tools/PenToolViewModel.cs
  23. 4 1
      src/PixiEditor/ViewModels/Tools/Tools/RasterEllipseToolViewModel.cs
  24. 4 1
      src/PixiEditor/ViewModels/Tools/Tools/RasterLineToolViewModel.cs
  25. 4 1
      src/PixiEditor/ViewModels/Tools/Tools/RasterRectangleToolViewModel.cs
  26. 2 1
      src/PixiEditor/ViewModels/Tools/Tools/RotateViewportToolViewModel.cs
  27. 3 1
      src/PixiEditor/ViewModels/Tools/Tools/SelectToolViewModel.cs
  28. 6 2
      src/PixiEditor/ViewModels/Tools/Tools/VectorEllipseToolViewModel.cs
  29. 4 1
      src/PixiEditor/ViewModels/Tools/Tools/VectorLineToolViewModel.cs
  30. 4 1
      src/PixiEditor/ViewModels/Tools/Tools/VectorRectangleToolViewModel.cs
  31. 2 1
      src/PixiEditor/ViewModels/Tools/Tools/ZoomToolViewModel.cs
  32. 11 6
      src/PixiEditor/Views/Main/Tools/ToolPickerButton.axaml

+ 11 - 13
src/PixiEditor.ChangeableDocument/Changes/Structure/CreateStructureMember_Change.cs

@@ -15,32 +15,30 @@ internal class CreateStructureMember_Change : Change
     private Guid newMemberGuid;
 
     private Guid parentGuid;
-    private StructureMemberType type;
+    private Type structureMemberOfType;
 
     [GenerateMakeChangeAction]
     public CreateStructureMember_Change(Guid parent, Guid newGuid,
-        StructureMemberType type)
+        Type ofType)
     {
         this.parentGuid = parent;
-        this.type = type;
+        this.structureMemberOfType = ofType;
         newMemberGuid = newGuid;
     }
 
     public override bool InitializeAndValidate(Document target)
     {
+        if(structureMemberOfType.IsAbstract || structureMemberOfType.IsInterface || !structureMemberOfType.IsAssignableTo(typeof(StructureNode)))
+            return false;
+        
         return target.TryFindNode<Node>(parentGuid, out _);
     }
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document document, bool firstApply,
         out bool ignoreInUndo)
     {
-        StructureNode member = type switch
-        {
-            // TODO: Add support for other types
-            StructureMemberType.Layer => new ImageLayerNode(document.Size) { Id = newMemberGuid },
-            StructureMemberType.Folder => new FolderNode() { Id = newMemberGuid },
-            _ => throw new NotSupportedException(),
-        };
+        StructureNode member = (StructureNode)NodeOperations.CreateNode(structureMemberOfType, document); 
+        member.Id = newMemberGuid;
 
         document.TryFindNode<Node>(parentGuid, out var parentNode);
 
@@ -71,10 +69,10 @@ internal class CreateStructureMember_Change : Change
 
     private IChangeInfo CreateChangeInfo(StructureNode member)
     {
-        return type switch
+        return member switch
         {
-            StructureMemberType.Layer => CreateLayer_ChangeInfo.FromLayer((LayerNode)member),
-            StructureMemberType.Folder => CreateFolder_ChangeInfo.FromFolder((FolderNode)member),
+            LayerNode layer => CreateLayer_ChangeInfo.FromLayer(layer),
+            FolderNode folderNode => CreateFolder_ChangeInfo.FromFolder(folderNode),
             _ => throw new NotSupportedException(),
         };
     }

+ 3 - 3
src/PixiEditor/Models/DocumentModels/ChangeExecutionController.cs

@@ -19,7 +19,7 @@ internal class ChangeExecutionController
     public VecD LastPrecisePosition => lastPrecisePos;
     public bool IsChangeActive => currentSession is not null;
     
-    public event Action ChangeFinished;
+    public event Action ToolSessionFinished;
 
     private readonly IDocument document;
     private readonly IServiceProvider services;
@@ -104,7 +104,7 @@ internal class ChangeExecutionController
         currentSession = null;
         _queuedExecutor = null;
         
-        ChangeFinished?.Invoke();
+        ToolSessionFinished?.Invoke();
     }
 
     public bool TryStopActiveExecutor()
@@ -114,7 +114,7 @@ internal class ChangeExecutionController
         currentSession.ForceStop();
         currentSession = null;
         
-        ChangeFinished?.Invoke();
+        ToolSessionFinished?.Invoke();
         return true;
     }
 

+ 31 - 5
src/PixiEditor/Models/DocumentModels/DocumentStructureHelper.cs

@@ -2,6 +2,7 @@
 using PixiEditor.ViewModels.Document;
 using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Handlers;
@@ -46,7 +47,7 @@ internal class DocumentStructureHelper
             //put member on top
             internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(
                 doc.NodeGraphHandler.OutputNode.Id,
-                guid, type));
+                guid, type == StructureMemberType.Layer ? typeof(ImageLayerNode) : typeof(FolderNode)));
             name ??= GetUniqueName(
                 type == StructureMemberType.Layer
                     ? new LocalizedString("NEW_LAYER")
@@ -61,7 +62,8 @@ internal class DocumentStructureHelper
         {
             Guid guid = Guid.NewGuid();
             //put member inside folder on top
-            internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(folder.Id, guid, type));
+            Type nodeType = type == StructureMemberType.Layer ? typeof(ImageLayerNode) : typeof(FolderNode);
+            internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(folder.Id, guid, nodeType));
             name ??= GetUniqueName(
                 type == StructureMemberType.Layer
                     ? new LocalizedString("NEW_LAYER")
@@ -77,10 +79,12 @@ internal class DocumentStructureHelper
             Guid guid = Guid.NewGuid();
             //put member above the layer
             INodeHandler parent = doc.StructureHelper.GetFirstForwardNode(layer);
-            if(parent is null)
+            if (parent is null)
                 parent = doc.NodeGraphHandler.OutputNode;
+
+            Type nodeType = type == StructureMemberType.Layer ? typeof(ImageLayerNode) : typeof(FolderNode);
             
-            internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(parent.Id, guid, type));
+            internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(parent.Id, guid, nodeType));
             name ??= GetUniqueName(
                 type == StructureMemberType.Layer
                     ? new LocalizedString("NEW_LAYER")
@@ -94,6 +98,27 @@ internal class DocumentStructureHelper
         throw new ArgumentException($"Unknown member type: {type}");
     }
 
+    public Guid? CreateNewStructureMember(Type structureMemberType, string? name, bool finish)
+    {
+        Guid guid = Guid.NewGuid();
+        var selectedMember = doc.SelectedStructureMember;
+        
+        //put member above the layer
+        INodeHandler parent = doc.StructureHelper.GetFirstForwardNode(selectedMember);
+        if (parent is null)
+            parent = doc.NodeGraphHandler.OutputNode;
+
+        internals.ActionAccumulator.AddActions(new CreateStructureMember_Action(parent.Id, guid, structureMemberType));
+        name ??= GetUniqueName(
+            structureMemberType.IsAssignableTo(typeof(LayerNode))
+                ? new LocalizedString("NEW_LAYER")
+                : new LocalizedString("NEW_FOLDER"), parent);
+        internals.ActionAccumulator.AddActions(new StructureMemberName_Action(guid, name));
+        if (finish)
+            internals.ActionAccumulator.AddFinishedActions();
+        return guid;
+    }
+
     private void HandleMoveInside(Guid memberToMove, Guid memberToMoveInto)
     {
         if (memberToMoveInto == memberToMove)
@@ -108,7 +133,8 @@ internal class DocumentStructureHelper
         var referenceMember = doc.StructureHelper.FindNode<INodeHandler>(referenceMemberId);
         var memberToMoveInto = !above ? referenceMember : doc.StructureHelper.GetFirstForwardNode(referenceMember);
         internals.ActionAccumulator.AddFinishedActions(
-            new MoveStructureMember_Action(memberToMove, memberToMoveInto.Id, above && memberToMoveInto is IFolderHandler));
+            new MoveStructureMember_Action(memberToMove, memberToMoveInto.Id,
+                above && memberToMoveInto is IFolderHandler));
     }
 
     public void TryMoveStructureMember(Guid memberToMove, Guid memberToMoveIntoOrNextTo,

+ 9 - 0
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -15,6 +15,7 @@ using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.Helpers;
+using PixiEditor.Models.DocumentModels.Public;
 using PixiEditor.Models.DocumentPassthroughActions;
 using PixiEditor.Models.Handlers;
 using PixiEditor.Models.Layers;
@@ -56,6 +57,9 @@ internal class DocumentUpdater
         //TODO: Find a more elegant way to do this
         switch (arbitraryInfo)
         {
+            case InvokeAction_PassthroughAction info:
+                ProcessInvokeAction(info);
+                break;
             case CreateStructureMember_ChangeInfo info:
                 ProcessCreateNode(info);
                 ProcessCreateStructureMember(info);
@@ -202,6 +206,11 @@ internal class DocumentUpdater
         }
     }
 
+    private void ProcessInvokeAction(InvokeAction_PassthroughAction info)
+    {
+        info.Action.Invoke();
+    }
+
     private void ProcessReferenceLayerIsVisible(ReferenceLayerIsVisible_ChangeInfo info)
     {
         doc.ReferenceLayerHandler.SetReferenceLayerIsVisible(info.IsVisible);

+ 20 - 1
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -4,6 +4,7 @@ using PixiEditor.ChangeableDocument.Actions;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Actions.Undo;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core.Surfaces.Vector;
@@ -155,6 +156,14 @@ internal class DocumentOperationsModule : IDocumentOperations
         return Internals.StructureHelper.CreateNewStructureMember(type, name, finish);
     }
 
+    public Guid? CreateStructureMember(Type structureMemberType, string? name = null, bool finish = true)
+    {
+        if (Internals.ChangeController.IsChangeActive)
+            return null;
+        
+        return Internals.StructureHelper.CreateNewStructureMember(structureMemberType, name, finish);
+    }
+
     /// <summary>
     /// Duplicates the layer with the <paramref name="guidValue"/>
     /// </summary>
@@ -444,7 +453,7 @@ internal class DocumentOperationsModule : IDocumentOperations
 
         //make a new layer, put combined image onto it, delete layers that were merged
         Internals.ActionAccumulator.AddActions(
-            new CreateStructureMember_Action(parent.Id, newGuid, StructureMemberType.Layer),
+            new CreateStructureMember_Action(parent.Id, newGuid, typeof(ImageLayerNode)),
             new StructureMemberName_Action(newGuid, node.NodeNameBindable),
             new CombineStructureMembersOnto_Action(members.ToHashSet(), newGuid,
                 Document.AnimationHandler.ActiveFrameBindable));
@@ -724,4 +733,14 @@ internal class DocumentOperationsModule : IDocumentOperations
 
         Internals.ActionAccumulator.AddFinishedActions(new RasterizeMember_Action(memberId));    
     }
+
+    public void InvokeCustomAction(Action action)
+    {
+        if (Internals.ChangeController.IsChangeActive)
+            return;
+
+        IAction targetAction = new InvokeAction_PassthroughAction(action);
+        
+        Internals.ActionAccumulator.AddActions(targetAction);
+    }
 }

+ 9 - 0
src/PixiEditor/Models/DocumentModels/Public/InvokeAction_PassthroughAction.cs

@@ -0,0 +1,9 @@
+using PixiEditor.ChangeableDocument.Actions;
+using PixiEditor.ChangeableDocument.ChangeInfos;
+
+namespace PixiEditor.Models.DocumentModels.Public;
+
+internal class InvokeAction_PassthroughAction(Action action) : IAction, IChangeInfo
+{
+    public Action Action { get; } = action;
+}

+ 7 - 3
src/PixiEditor/Models/Handlers/IToolHandler.cs

@@ -13,7 +13,7 @@ internal interface IToolHandler : IHandler
     public string ToolName => GetType().Name.Replace("Tool", string.Empty).Replace("ViewModel", string.Empty);
     public string ToolNameLocalizationKey { get; }
     public string Icon => $"icon-{ToolName.ToLower()}";
-    //public virtual BrushShape BrushShape => BrushShape.Square;
+    public Type[]? SupportedLayerTypes { get; }
 
     public bool HideHighlight { get; }
 
@@ -47,8 +47,12 @@ internal interface IToolHandler : IHandler
     public LocalizedString ActionDisplay { get; set; }
     public bool IsActive { get; set; }
     public Cursor Cursor { get; set; }
-    public bool CanBeUsed { get; }
-    //public Toolbar Toolbar { get; set; }
+    public bool CanBeUsedOnActiveLayer { get; }
+    
+    /// <summary>
+    ///     Layer type that should be created if no layer is selected incompatible one.
+    /// </summary>
+    public Type LayerTypeToCreateOnEmptyUse { get; }
 
     public void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown);
     public void UseTool(VecD pos);

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

@@ -37,7 +37,7 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>, IDocument
             if (ViewModelMain.Current.ToolsSubViewModel.ActiveTool == null)
             {
                 var firstTool =
-                    ViewModelMain.Current.ToolsSubViewModel.ActiveToolSet.Tools.FirstOrDefault(x => x.CanBeUsed);
+                    ViewModelMain.Current.ToolsSubViewModel.ActiveToolSet.Tools.FirstOrDefault(x => x.CanBeUsedOnActiveLayer);
                 if (firstTool != null)
                 {
                     ViewModelMain.Current.ToolsSubViewModel.SetActiveTool(firstTool.GetType(), false);

+ 2 - 2
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -61,7 +61,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
 {
     public event EventHandler<LayersChangedEventArgs>? LayersChanged;
     public event EventHandler<DocumentSizeChangedEventArgs>? SizeChanged;
-    public event Action FinishedChange;
+    public event Action ToolSessionFinished;
 
     private bool busy = false;
 
@@ -219,7 +219,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
     {
         var serviceProvider = ViewModelMain.Current.Services;
         Internals = new DocumentInternalParts(this, serviceProvider);
-        Internals.ChangeController.ChangeFinished += () => FinishedChange?.Invoke();
+        Internals.ChangeController.ToolSessionFinished += () => ToolSessionFinished?.Invoke();
         
         Tools = new DocumentToolsModule(this, Internals);
         StructureHelper = new DocumentStructureModule(this);

+ 5 - 5
src/PixiEditor/ViewModels/SubViewModels/IoViewModel.cs

@@ -215,7 +215,7 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
                 }
                 else
                 {
-                    Owner.DocumentManagerSubViewModel.ActiveDocument.FinishedChange += FinishedChange;
+                    Owner.DocumentManagerSubViewModel.ActiveDocument.ToolSessionFinished += ToolSessionFinished;
                 }
 
                 hadSwapped = true;
@@ -316,8 +316,8 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
                 }
                 else
                 {
-                    Owner.DocumentManagerSubViewModel.ActiveDocument.FinishedChange +=
-                        FinishedChange;
+                    Owner.DocumentManagerSubViewModel.ActiveDocument.ToolSessionFinished +=
+                        ToolSessionFinished;
                 }
 
                 break;
@@ -327,10 +327,10 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
         }
     }
     
-    private void FinishedChange()
+    private void ToolSessionFinished()
     {
         Owner.ColorsSubViewModel.SwapColors(null);
-        Owner.DocumentManagerSubViewModel.ActiveDocument.FinishedChange -= FinishedChange;
+        Owner.DocumentManagerSubViewModel.ActiveDocument.ToolSessionFinished -= ToolSessionFinished;
     }
 
     private void HandleRightMouseEraseUp(IToolsHandler tools)

+ 9 - 0
src/PixiEditor/ViewModels/SubViewModels/LayersViewModel.cs

@@ -122,9 +122,18 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
     {
         if (Owner.DocumentManagerSubViewModel.ActiveDocument is not { } doc)
             return;
+        
         doc.Operations.CreateStructureMember(StructureMemberType.Layer);
     }
 
+    public Guid? NewLayer(Type layerType, string? name = null, bool finish = true)
+    {
+        if (Owner.DocumentManagerSubViewModel.ActiveDocument is not { } doc)
+            return null;
+        
+        return doc.Operations.CreateStructureMember(layerType, name, finish);
+    }
+
     [Evaluator.CanExecute("PixiEditor.Layer.CanCreateNewMember")]
     public bool CanCreateNewMember()
     {

+ 26 - 6
src/PixiEditor/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -4,6 +4,7 @@ using System.ComponentModel;
 using System.Linq;
 using Avalonia.Input;
 using Microsoft.Extensions.DependencyInjection;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Models.Preferences;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.CommonApi.UserPreferences.Settings.PixiEditor;
@@ -179,7 +180,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
         {
             nextIndex = 0;
         }
-        
+
         if (nextIndex < 0)
         {
             nextIndex = AllToolSets.Count - 1;
@@ -313,7 +314,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
         if (!typeof(ToolViewModel).IsAssignableFrom(toolType))
             throw new ArgumentException($"'{toolType}' does not inherit from {typeof(ToolViewModel)}");
         IToolHandler foundTool = ActiveToolSet!.Tools.FirstOrDefault(x => x.GetType().IsAssignableFrom(toolType));
-        if (foundTool == null || !foundTool.CanBeUsed) return;
+        if (foundTool == null) return;
 
         SetActiveTool(foundTool, transient, sourceInfo);
     }
@@ -362,15 +363,34 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
 
     public void UseToolEventInlet(VecD canvasPos, MouseButton button)
     {
-        if (ActiveTool is not { CanBeUsed: true }) return;
-
         ActiveTool.UsedWith = button;
         if (ActiveTool.StopsLinkedToolOnUse)
         {
             ViewModelMain.Current.DocumentManagerSubViewModel.ActiveDocument?.Operations.TryStopToolLinkedExecutor();
         }
 
-        ActiveTool.UseTool(canvasPos);
+        bool waitForChange = false;
+
+        if (ActiveTool is not { CanBeUsedOnActiveLayer: true })
+        {
+            Guid? createdLayer = Owner.LayersSubViewModel.NewLayer(ActiveTool.LayerTypeToCreateOnEmptyUse);
+            if (createdLayer is not null)
+            {
+                Owner.DocumentManagerSubViewModel.ActiveDocument.Operations.SetSelectedMember(createdLayer.Value);
+            }
+
+            waitForChange = true;
+        }
+
+        if (waitForChange)
+        {
+            Owner.DocumentManagerSubViewModel.ActiveDocument.Operations
+                .InvokeCustomAction(() => ActiveTool.UseTool(canvasPos));
+        }
+        else
+        {
+            ActiveTool.UseTool(canvasPos);
+        }
     }
 
     public void ConvertedKeyDownInlet(FilteredKeyEventArgs args)
@@ -444,7 +464,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
         if (doc is null)
             return;
-        
+
         foreach (var toolHandler in ActiveToolSet.Tools)
         {
             if (toolHandler is ToolViewModel tool)

+ 39 - 28
src/PixiEditor/ViewModels/Tools/ToolViewModel.cs

@@ -15,7 +15,7 @@ namespace PixiEditor.ViewModels.Tools;
 
 internal abstract class ToolViewModel : ObservableObject, IToolHandler
 {
-    private bool canBeSelected = true;
+    private bool canBeUsedOnActiveLayerOnActiveLayer = true;
     public bool IsTransient { get; set; } = false;
     public KeyCombination Shortcut { get; set; }
 
@@ -27,19 +27,21 @@ internal abstract class ToolViewModel : ObservableObject, IToolHandler
     public virtual string Icon => $"\u25a1";
 
     public virtual BrushShape BrushShape => BrushShape.Square;
-    
-    public abstract Type[] SupportedLayerTypes { get; }
 
-    public bool CanBeUsed
+    public abstract Type[]? SupportedLayerTypes { get; }
+
+    public bool CanBeUsedOnActiveLayer
     {
-        get => canBeSelected;
+        get => canBeUsedOnActiveLayerOnActiveLayer;
         private set
         {
-            canBeSelected = value;
-            OnPropertyChanged(nameof(CanBeUsed));
+            canBeUsedOnActiveLayerOnActiveLayer = value;
+            OnPropertyChanged(nameof(CanBeUsedOnActiveLayer));
         }
     }
 
+    public abstract Type LayerTypeToCreateOnEmptyUse { get; }
+
     public virtual bool HideHighlight { get; }
 
     public abstract LocalizedString Tooltip { get; }
@@ -49,12 +51,12 @@ internal abstract class ToolViewModel : ObservableObject, IToolHandler
     /// </summary>
     public virtual bool UsesColor => false;
 
-   /// <summary>
-   /// Determines if PixiEditor should switch to the Eraser when right click mode is set to erase
-   /// </summary>
+    /// <summary>
+    /// Determines if PixiEditor should switch to the Eraser when right click mode is set to erase
+    /// </summary>
     public virtual bool IsErasable => false;
 
-   /// <inheritdoc cref="IToolHandler.StopsLinkedToolOnUse"/>
+    /// <inheritdoc cref="IToolHandler.StopsLinkedToolOnUse"/>
     public virtual bool StopsLinkedToolOnUse => true;
 
     /// <summary>
@@ -63,6 +65,7 @@ internal abstract class ToolViewModel : ObservableObject, IToolHandler
     public MouseButton UsedWith { get; set; }
 
     private LocalizedString actionDisplay = string.Empty;
+
     public LocalizedString ActionDisplay
     {
         get => actionDisplay;
@@ -74,6 +77,7 @@ internal abstract class ToolViewModel : ObservableObject, IToolHandler
     }
 
     private bool isActive;
+
     public bool IsActive
     {
         get => isActive;
@@ -92,28 +96,33 @@ internal abstract class ToolViewModel : ObservableObject, IToolHandler
     {
         ILocalizationProvider.Current.OnLanguageChanged += OnLanguageChanged;
     }
-    
+
     internal void SelectedLayersChanged(IStructureMemberHandler[] layers)
     {
-        foreach (var layer in layers)
+        if (layers.Length is > 1 or 0)
+        {
+            CanBeUsedOnActiveLayer = false;
+            return;
+        }
+        
+        var layer = layers[0];
+
+        if (SupportedLayerTypes == null)
         {
-            if(SupportedLayerTypes == null || SupportedLayerTypes.Length == 0)
+            CanBeUsedOnActiveLayer = true;
+            return;
+        }
+
+        foreach (var type in SupportedLayerTypes)
+        {
+            if (type.IsInstanceOfType(layer))
             {
-                CanBeUsed = true;
+                CanBeUsedOnActiveLayer = true;
                 return;
             }
-            
-            foreach (var type in SupportedLayerTypes)
-            {
-                if (type.IsInstanceOfType(layer))
-                {
-                    CanBeUsed = true;
-                    return;
-                }
-            }
         }
-        
-        CanBeUsed = false;
+
+        CanBeUsedOnActiveLayer = false;
     }
 
     private void OnLanguageChanged(Language obj)
@@ -127,7 +136,8 @@ internal abstract class ToolViewModel : ObservableObject, IToolHandler
     public virtual void OnSelected() { }
 
     public virtual void OnDeselecting()
-    { }
+    {
+    }
 
     protected T GetValue<T>([CallerMemberName] string name = null)
     {
@@ -135,7 +145,8 @@ internal abstract class ToolViewModel : ObservableObject, IToolHandler
 
         if (setting.GetSettingType().IsAssignableTo(typeof(Enum)))
         {
-            var property = setting.GetType().GetProperty("Value",  BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
+            var property = setting.GetType().GetProperty("Value",
+                BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
             return (T)property!.GetValue(setting);
         }
 

+ 4 - 1
src/PixiEditor/ViewModels/Tools/Tools/BrightnessToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
@@ -32,7 +33,7 @@ internal class BrightnessToolViewModel : ToolViewModel, IBrightnessToolHandler
 
     public override string Icon => PixiPerfectIcons.Sun;
 
-    public override Type[] SupportedLayerTypes { get; } =
+    public override Type[]? SupportedLayerTypes { get; } =
     {
         typeof(IRasterLayerHandler)
     };
@@ -55,6 +56,8 @@ internal class BrightnessToolViewModel : ToolViewModel, IBrightnessToolHandler
 
     float IBrightnessToolHandler.CorrectionFactor => CorrectionFactor;
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(ImageLayerNode);
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (!ctrlIsDown)

+ 2 - 1
src/PixiEditor/ViewModels/Tools/Tools/ColorPickerToolViewModel.cs

@@ -22,6 +22,7 @@ internal class ColorPickerToolViewModel : ToolViewModel, IColorPickerHandler
 
     private readonly string defaultActionDisplay = "COLOR_PICKER_ACTION_DISPLAY_CANVAS_ONLY";
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = null;
     public override bool HideHighlight => true;
 
     public override bool UsesColor => true;
@@ -31,7 +32,7 @@ internal class ColorPickerToolViewModel : ToolViewModel, IColorPickerHandler
 
     public override string Icon => PixiPerfectIcons.Picker;
 
-    public override Type[] SupportedLayerTypes { get; } = [];  // all layer types are supported
+    public override Type[]? SupportedLayerTypes { get; } = null;  // all layer types are supported
 
     public override LocalizedString Tooltip => new("COLOR_PICKER_TOOLTIP", Shortcut);
 

+ 4 - 1
src/PixiEditor/ViewModels/Tools/Tools/EraserToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
@@ -27,7 +28,7 @@ internal class EraserToolViewModel : ToolViewModel, IEraserToolHandler
 
     public override string ToolNameLocalizationKey => "ERASER_TOOL";
     public override BrushShape BrushShape => BrushShape.Circle;
-    public override Type[] SupportedLayerTypes { get; } =
+    public override Type[]? SupportedLayerTypes { get; } =
     {
         typeof(IRasterLayerHandler)
     };
@@ -36,6 +37,8 @@ internal class EraserToolViewModel : ToolViewModel, IEraserToolHandler
 
     public override LocalizedString Tooltip => new LocalizedString("ERASER_TOOL_TOOLTIP", Shortcut);
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(ImageLayerNode);
+
     public override void UseTool(VecD pos)
     {
         ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseEraserTool();

+ 4 - 1
src/PixiEditor/ViewModels/Tools/Tools/FloodFillToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
@@ -17,7 +18,7 @@ internal class FloodFillToolViewModel : ToolViewModel, IFloodFillToolHandler
 
     public override string ToolNameLocalizationKey => "FLOOD_FILL_TOOL";
     public override BrushShape BrushShape => BrushShape.Pixel;
-    public override Type[] SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
+    public override Type[]? SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
 
     public override LocalizedString Tooltip => new("FLOOD_FILL_TOOL_TOOLTIP", Shortcut);
 
@@ -34,6 +35,8 @@ internal class FloodFillToolViewModel : ToolViewModel, IFloodFillToolHandler
         ActionDisplay = defaultActionDisplay;
     }
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(ImageLayerNode);
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (ctrlIsDown)

+ 3 - 1
src/PixiEditor/ViewModels/Tools/Tools/LassoToolViewModel.cs

@@ -25,6 +25,8 @@ internal class LassoToolViewModel : ToolViewModel, ILassoToolHandler
     private SelectionMode KeyModifierselectionMode = SelectionMode.New;
     public SelectionMode? ResultingSelectionMode => KeyModifierselectionMode != SelectionMode.New ? KeyModifierselectionMode : SelectMode;
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = null;
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (shiftIsDown)
@@ -50,7 +52,7 @@ internal class LassoToolViewModel : ToolViewModel, ILassoToolHandler
     public string Icon => PixiPerfectIcons.Lasso;
     public override BrushShape BrushShape => BrushShape.Pixel;
     
-    public override Type[] SupportedLayerTypes { get; } = []; // all layer types are supported
+    public override Type[]? SupportedLayerTypes { get; } = null; // all layer types are supported
 
     [Settings.Enum("MODE_LABEL")]
     public SelectionMode SelectMode => GetValue<SelectionMode>();

+ 4 - 2
src/PixiEditor/ViewModels/Tools/Tools/MagicWandToolViewModel.cs

@@ -20,7 +20,7 @@ internal class MagicWandToolViewModel : ToolViewModel, IMagicWandToolHandler
 
     public override string ToolNameLocalizationKey => "MAGIC_WAND_TOOL";
     public override BrushShape BrushShape => BrushShape.Pixel;
-    public override Type[] SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) }; 
+    public override Type[]? SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) }; 
 
     [Settings.Enum("MODE_LABEL")]
     public SelectionMode SelectMode => GetValue<SelectionMode>();
@@ -35,7 +35,9 @@ internal class MagicWandToolViewModel : ToolViewModel, IMagicWandToolHandler
         Toolbar = ToolbarFactory.Create(this);
         ActionDisplay = "MAGIC_WAND_ACTION_DISPLAY";
     }
-    
+
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = null;
+
     public override void UseTool(VecD pos)
     {
         ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseMagicWandTool();

+ 2 - 1
src/PixiEditor/ViewModels/Tools/Tools/MoveToolViewModel.cs

@@ -39,7 +39,8 @@ internal class MoveToolViewModel : ToolViewModel, IMoveToolHandler
     public bool KeepOriginalImage => GetValue<bool>();
 
     public override BrushShape BrushShape => BrushShape.Hidden;
-    public override Type[] SupportedLayerTypes { get; } = [];
+    public override Type[]? SupportedLayerTypes { get; } = null;
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = null;
     public override bool HideHighlight => true;
 
     public bool TransformingSelectedArea

+ 2 - 1
src/PixiEditor/ViewModels/Tools/Tools/MoveViewportToolViewModel.cs

@@ -11,7 +11,8 @@ internal class MoveViewportToolViewModel : ToolViewModel
 {
     public override string ToolNameLocalizationKey => "MOVE_VIEWPORT_TOOL";
     public override BrushShape BrushShape => BrushShape.Hidden;
-    public override Type[] SupportedLayerTypes { get; } = [];
+    public override Type[]? SupportedLayerTypes { get; } = null;
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = null;
     public override bool HideHighlight => true;
     public override LocalizedString Tooltip => new LocalizedString("MOVE_VIEWPORT_TOOLTIP", Shortcut);
 

+ 5 - 4
src/PixiEditor/ViewModels/Tools/Tools/PenToolViewModel.cs

@@ -1,6 +1,5 @@
-using System.Linq;
-using Avalonia.Input;
-using PixiEditor.DrawingApi.Core.Numerics;
+using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Extensions.CommonApi.UserPreferences.Settings.PixiEditor;
 using PixiEditor.Models.Commands.Attributes.Commands;
@@ -23,7 +22,7 @@ namespace PixiEditor.ViewModels.Tools.Tools
         public override string ToolNameLocalizationKey => "PEN_TOOL";
         public override BrushShape BrushShape => BrushShape.Circle;
         
-        public override Type[] SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
+        public override Type[]? SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
 
         public PenToolViewModel()
         {
@@ -43,6 +42,8 @@ namespace PixiEditor.ViewModels.Tools.Tools
 
         public override string Icon => PixiPerfectIcons.Pen;
 
+        public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(ImageLayerNode);
+
         public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
         {
             ActionDisplay = new LocalizedString("PEN_TOOL_ACTION_DISPLAY", Shortcut);

+ 4 - 1
src/PixiEditor/ViewModels/Tools/Tools/RasterEllipseToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
@@ -20,12 +21,14 @@ internal class RasterEllipseToolViewModel : ShapeTool, IRasterEllipseToolHandler
         ActionDisplay = defaultActionDisplay;
     }
 
-    public override Type[] SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
+    public override Type[]? SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
     public override LocalizedString Tooltip => new LocalizedString("ELLIPSE_TOOL_TOOLTIP", Shortcut);
     public bool DrawCircle { get; private set; }
 
     public override string Icon => PixiPerfectIcons.Circle;
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(ImageLayerNode);
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (shiftIsDown)

+ 4 - 1
src/PixiEditor/ViewModels/Tools/Tools/RasterLineToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Views.Overlays.BrushShapeOverlay;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
@@ -25,13 +26,15 @@ internal class RasterLineToolViewModel : ShapeTool, ILineToolHandler
     public override string ToolNameLocalizationKey => "LINE_TOOL";
     public override LocalizedString Tooltip => new LocalizedString("LINE_TOOL_TOOLTIP", Shortcut);
 
-    public override Type[] SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
+    public override Type[]? SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
     public override string Icon => PixiPerfectIcons.Line;
 
     [Settings.Inherited] public int ToolSize => GetValue<int>();
 
     public bool Snap { get; private set; }
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(ImageLayerNode);
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (shiftIsDown)

+ 4 - 1
src/PixiEditor/ViewModels/Tools/Tools/RasterRectangleToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
@@ -19,7 +20,7 @@ internal class RasterRectangleToolViewModel : ShapeTool, IRasterRectangleToolHan
     }
 
     public override string ToolNameLocalizationKey => "RECTANGLE_TOOL";
-    public override Type[] SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
+    public override Type[]? SupportedLayerTypes { get; } = { typeof(IRasterLayerHandler) };
     public override LocalizedString Tooltip => new LocalizedString("RECTANGLE_TOOL_TOOLTIP", Shortcut);
 
     public bool Filled { get; set; } = false;
@@ -27,6 +28,8 @@ internal class RasterRectangleToolViewModel : ShapeTool, IRasterRectangleToolHan
 
     public override string Icon => PixiPerfectIcons.Square;
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(ImageLayerNode);
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (shiftIsDown)

+ 2 - 1
src/PixiEditor/ViewModels/Tools/Tools/RotateViewportToolViewModel.cs

@@ -11,7 +11,8 @@ internal class RotateViewportToolViewModel : ToolViewModel
 {
     public override string ToolNameLocalizationKey => "ROTATE_VIEWPORT_TOOL";
     public override BrushShape BrushShape => BrushShape.Hidden;
-    public override Type[] SupportedLayerTypes { get; } = [];
+    public override Type[]? SupportedLayerTypes { get; } = null; // null = all
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = null;
     public override bool HideHighlight => true;
     public override bool StopsLinkedToolOnUse => false;
     public override LocalizedString Tooltip => new LocalizedString("ROTATE_VIEWPORT_TOOLTIP", Shortcut);

+ 3 - 1
src/PixiEditor/ViewModels/Tools/Tools/SelectToolViewModel.cs

@@ -30,6 +30,8 @@ internal class SelectToolViewModel : ToolViewModel, ISelectToolHandler
     private SelectionMode KeyModifierselectionMode = SelectionMode.New;
     public SelectionMode ResultingSelectionMode => KeyModifierselectionMode != SelectionMode.New ? KeyModifierselectionMode : SelectMode;
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = null;
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (shiftIsDown)
@@ -56,7 +58,7 @@ internal class SelectToolViewModel : ToolViewModel, ISelectToolHandler
     public SelectionShape SelectShape => GetValue<SelectionShape>();
 
     public override BrushShape BrushShape => BrushShape.Pixel;
-    public override Type[] SupportedLayerTypes { get; } = [];
+    public override Type[]? SupportedLayerTypes { get; } = [];
 
     public override LocalizedString Tooltip => new LocalizedString("SELECT_TOOL_TOOLTIP", Shortcut);
 

+ 6 - 2
src/PixiEditor/ViewModels/Tools/Tools/VectorEllipseToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Handlers;
@@ -18,13 +19,16 @@ internal class VectorEllipseToolViewModel : ShapeTool, IVectorEllipseToolHandler
     {
         ActionDisplay = defaultActionDisplay;
     }
-
-    public override Type[] SupportedLayerTypes { get; } = { typeof(IVectorLayerHandler) };
+    
+    // This doesn't include a Vector layer because it is designed to create new layer each use
+    public override Type[]? SupportedLayerTypes { get; } = []; 
     public override LocalizedString Tooltip => new LocalizedString("ELLIPSE_TOOL_TOOLTIP", Shortcut);
     public bool DrawCircle { get; private set; }
 
     public override string Icon => PixiPerfectIcons.Circle;
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(VectorLayerNode);
+
     public override void UseTool(VecD pos)
     {
         ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorEllipseTool();

+ 4 - 1
src/PixiEditor/ViewModels/Tools/Tools/VectorLineToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Views.Overlays.BrushShapeOverlay;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
@@ -26,13 +27,15 @@ internal class VectorLineToolViewModel : ShapeTool, IVectorLineToolHandler
     public override LocalizedString Tooltip => new LocalizedString("LINE_TOOL_TOOLTIP", Shortcut);
 
     public override string Icon => PixiPerfectIcons.Line;
-    public override Type[] SupportedLayerTypes { get; } = { typeof(IVectorLayerHandler) };
+    public override Type[]? SupportedLayerTypes { get; } = [];
 
     [Settings.Inherited]
     public int ToolSize => GetValue<int>();
 
     public bool Snap { get; private set; }
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(VectorLayerNode);
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (shiftIsDown)

+ 4 - 1
src/PixiEditor/ViewModels/Tools/Tools/VectorRectangleToolViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Input;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Handlers;
@@ -19,12 +20,14 @@ internal class VectorRectangleToolViewModel : ShapeTool, IVectorRectangleToolHan
         ActionDisplay = defaultActionDisplay;
     }
 
-    public override Type[] SupportedLayerTypes { get; } = { typeof(IVectorLayerHandler) };
+    public override Type[]? SupportedLayerTypes { get; } = [];
     public override LocalizedString Tooltip => new LocalizedString("RECTANGLE_TOOL_TOOLTIP", Shortcut);
     public bool DrawSquare { get; private set; }
 
     public override string Icon => PixiPerfectIcons.Square;
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(VectorLayerNode);
+
     public override void ModifierKeyChanged(bool ctrlIsDown, bool shiftIsDown, bool altIsDown)
     {
         if (shiftIsDown)

+ 2 - 1
src/PixiEditor/ViewModels/Tools/Tools/ZoomToolViewModel.cs

@@ -20,7 +20,7 @@ internal class ZoomToolViewModel : ToolViewModel
 
     public override string ToolNameLocalizationKey => "ZOOM_TOOL";
     public override BrushShape BrushShape => BrushShape.Hidden;
-    public override Type[] SupportedLayerTypes { get; } = [];
+    public override Type[]? SupportedLayerTypes { get; } = [];
 
     public override bool StopsLinkedToolOnUse => false;
 
@@ -31,6 +31,7 @@ internal class ZoomToolViewModel : ToolViewModel
         ActionDisplay = defaultActionDisplay;
     }
 
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = null;
     public override bool HideHighlight => true;
 
     public override LocalizedString Tooltip => new LocalizedString("ZOOM_TOOL_TOOLTIP", Shortcut);

+ 11 - 6
src/PixiEditor/Views/Main/Tools/ToolPickerButton.axaml

@@ -16,21 +16,26 @@
     </Design.DataContext>
     <Button Command="{xaml:Command PixiEditor.Tools.SelectTool, UseProvided=true}"
             CommandParameter="{Binding}"
-            IsEnabled="{Binding CanBeUsed}"
             Width="44" Height="34"
             ui:Translator.TooltipKey="{Binding DisplayName}"
             Background="{DynamicResource ThemeBackgroundBrush1}">
         <Button.Template>
             <ControlTemplate>
-                <Border Height="34" Width="34" 
+                <Border Height="34" Width="34"
                         Background="{DynamicResource ThemeBackgroundBrush1}">
-                    <ContentPresenter Content="{TemplateBinding Content}"/>
+                    <ContentPresenter Content="{TemplateBinding Content}" />
                 </Border>
             </ControlTemplate>
         </Button.Template>
         <Button.Content>
-            <TextBlock Classes="pixi-icon" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center"
-                       Text="{Binding Path=Icon}"/>
+            <Grid>
+                <TextBlock Classes="pixi-icon" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center"
+                           Text="{Binding Path=Icon}" />
+                <TextBlock Background="{DynamicResource ThemeBorderLowBrush}"
+                           IsVisible="{Binding !CanBeUsedOnActiveLayer}"
+                           Classes="pixi-icon" FontSize="12" Text="{DynamicResource icon-plus-square}" 
+                           HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
+            </Grid>
         </Button.Content>
     </Button>
-</UserControl>
+</UserControl>