Jelajahi Sumber

rasterize, convert to curve for all members

Krzysztof Krysiński 2 bulan lalu
induk
melakukan
a805d08576

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Structure/RasterizeMember_Change.cs

@@ -125,6 +125,6 @@ internal class RasterizeMember_Change : Change
 
     public override void Dispose()
     {
-        originalNode.Dispose();
+        originalNode?.Dispose();
     }
 }

+ 3 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -1053,5 +1053,7 @@
   "SEPARATE_SHAPES_DESCRIPTIVE": "Separate shapes from current vector into individual layers",
   "TEXT": "Text",
   "EXTRACT_SELECTED_TEXT": "Extract selected text",
-    "EXTRACT_SELECTED_TEXT_DESCRIPTIVE": "Extract selected text into new layer."
+  "EXTRACT_SELECTED_TEXT_DESCRIPTIVE": "Extract selected text into new layer.",
+  "EXTRACT_SELECTED_CHARACTERS": "Extract selected characters",
+  "EXTRACT_SELECTED_CHARACTERS_DESCRIPTIVE": "Extract individual characters from selection into new layers."
 }

+ 88 - 16
src/PixiEditor/ViewModels/SubViewModels/LayersViewModel.cs

@@ -23,6 +23,7 @@ using PixiEditor.Models.Handlers;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.Layers;
 using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.Helpers;
 using PixiEditor.UI.Common.Fonts;
 using PixiEditor.UI.Common.Localization;
@@ -249,6 +250,55 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
         return member is IVectorLayerHandler;
     }
 
+    [Evaluator.CanExecute("PixiEditor.Layer.AnySelectedMemberIsVectorLayer",
+        nameof(DocumentManagerViewModel.ActiveDocument), nameof(DocumentViewModel.SelectedStructureMember))]
+    public bool AnySelectedMemberIsVectorLayer(object property)
+    {
+        var members = Owner.DocumentManagerSubViewModel.ActiveDocument?.ExtractSelectedLayers();
+
+        if (members is null || members.Count == 0)
+            return false;
+
+        var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
+        if (doc is null)
+            return false;
+
+        foreach (var member in members)
+        {
+            var handler = doc.StructureHelper.Find(member);
+            if (handler is IVectorLayerHandler)
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    [Evaluator.CanExecute("PixiEditor.Layer.AnySelectedLayerIsRasterizable",
+        nameof(DocumentManagerViewModel.ActiveDocument), nameof(DocumentViewModel.SelectedStructureMember))]
+    public bool AnySelectedMemberIsRasterizable(object property)
+    {
+        var members = Owner.DocumentManagerSubViewModel.ActiveDocument?.ExtractSelectedLayers();
+
+        if (members is null || members.Count == 0)
+            return false;
+
+        var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
+        if (doc is null)
+            return false;
+
+        foreach (var member in members)
+        {
+            var handler = doc.StructureHelper.Find(member);
+            if (handler is ILayerHandler && handler is not IRasterLayerHandler)
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
 
     [Evaluator.CanExecute("PixiEditor.Layer.SelectedMemberIsSelectedText",
         nameof(DocumentManagerViewModel.ActiveDocument), nameof(DocumentViewModel.SelectedStructureMember))]
@@ -563,56 +613,78 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Basic("PixiEditor.Layer.Rasterize", "RASTERIZE_ACTIVE_LAYER", "RASTERIZE_ACTIVE_LAYER_DESCRIPTIVE",
-        CanExecute = "PixiEditor.Layer.SelectedLayerIsRasterizable",
+        CanExecute = "PixiEditor.Layer.AnySelectedLayerIsRasterizable",
         Icon = PixiPerfectIcons.LowResCircle, MenuItemPath = "LAYER/VECTOR/RASTERIZE_ACTIVE_LAYER",
         AnalyticsTrack = true)]
     public void RasterizeActiveLayer()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
-        var member = doc?.SelectedStructureMember;
-        if (member is null)
+        var selectedMembers = doc.ExtractSelectedLayers();
+        if (selectedMembers.Count == 0)
             return;
 
-        doc!.Operations.Rasterize(member.Id);
+        var block = doc.Operations.StartChangeBlock();
+
+        foreach (var member in selectedMembers)
+        {
+            doc!.Operations.Rasterize(member);
+        }
+
+        block.Dispose();
     }
 
     [Command.Basic("PixiEditor.Layer.ConvertToCurve", "CONVERT_TO_CURVE", "CONVERT_TO_CURVE_DESCRIPTIVE",
-        CanExecute = "PixiEditor.Layer.SelectedMemberIsVectorLayer",
+        CanExecute = "PixiEditor.Layer.AnySelectedMemberIsVectorLayer",
         MenuItemPath = "LAYER/VECTOR/CONVERT_TO_CURVE", AnalyticsTrack = true)]
-    public void ConvertActiveLayerToCurve()
+    public void ConvertActiveLayersToCurve()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
-        var member = doc?.SelectedStructureMember;
-        if (member is null)
+        var selectedMembers = doc.ExtractSelectedLayers();
+        if (selectedMembers.Count == 0)
             return;
 
-        doc!.Operations.ConvertToCurve(member.Id);
+        var block = doc.Operations.StartChangeBlock();
+
+        foreach (var member in selectedMembers)
+        {
+            doc!.Operations.ConvertToCurve(member);
+        }
+
+        block.Dispose();
     }
 
     [Command.Basic("PixiEditor.Layer.SeparateShapes", "SEPARATE_SHAPES", "SEPARATE_SHAPES_DESCRIPTIVE",
-        CanExecute = "PixiEditor.Layer.SelectedMemberIsVectorLayer",
+        CanExecute = "PixiEditor.Layer.AnySelectedMemberIsVectorLayer",
         MenuItemPath = "LAYER/VECTOR/SEPARATE_SHAPES", AnalyticsTrack = true)]
     public void SeparateShapes()
     {
         var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
-        var member = doc?.SelectedStructureMember;
-        if (member is null)
+        var selectedMembers = doc.ExtractSelectedLayers();
+        if (selectedMembers.Count == 0)
             return;
 
-        doc!.Operations.SeparateShapes(member.Id);
+        var block = doc.Operations.StartChangeBlock();
+
+        foreach (var member in selectedMembers)
+        {
+            doc!.Operations.SeparateShapes(member);
+        }
+
+        block.Dispose();
     }
 
     [Command.Basic("PixiEditor.Layer.ExtractSelectedText", "EXTRACT_SELECTED_TEXT", "EXTRACT_SELECTED_TEXT_DESCRIPTIVE",
         CanExecute = "PixiEditor.Layer.SelectedMemberIsSelectedText",
         Key = Key.X, Modifiers = KeyModifiers.Control | KeyModifiers.Shift,
         Parameter = false,
-        ShortcutContexts = [ typeof(ViewportWindowViewModel), typeof(TextOverlay)],
+        ShortcutContexts = [typeof(ViewportWindowViewModel), typeof(TextOverlay)],
         MenuItemPath = "LAYER/TEXT/EXTRACT_SELECTED_TEXT", AnalyticsTrack = true)]
-    [Command.Basic("PixiEditor.Layer.ExtractSelectedCharacters", "EXTRACT_SELECTED_CHARACTERS", "EXTRACT_SELECTED_CHARACTERS_DESCRIPTIVE",
+    [Command.Basic("PixiEditor.Layer.ExtractSelectedCharacters", "EXTRACT_SELECTED_CHARACTERS",
+        "EXTRACT_SELECTED_CHARACTERS_DESCRIPTIVE",
         CanExecute = "PixiEditor.Layer.SelectedMemberIsSelectedText",
         Key = Key.X, Modifiers = KeyModifiers.Control | KeyModifiers.Shift | KeyModifiers.Alt,
         Parameter = true,
-        ShortcutContexts = [ typeof(ViewportWindowViewModel), typeof(TextOverlay)],
+        ShortcutContexts = [typeof(ViewportWindowViewModel), typeof(TextOverlay)],
         MenuItemPath = "LAYER/TEXT/EXTRACT_SELECTED_CHARACTERS", AnalyticsTrack = true)]
     public void ExtractSelectedText(bool extractEachCharacter)
     {