Bladeren bron

ShapeToolExecutor

flabbet 3 jaren geleden
bovenliggende
commit
56e7ff173e

+ 9 - 78
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/EllipseToolExecutor.cs

@@ -1,50 +1,11 @@
-using System.Windows.Input;
-using ChunkyImageLib.DataHolders;
-using PixiEditor.Models.Enums;
-using PixiEditor.ViewModels.SubViewModels.Document;
+using ChunkyImageLib.DataHolders;
+using PixiEditor.ChangeableDocument.Actions;
 using PixiEditor.ViewModels.SubViewModels.Tools.Tools;
-using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
-internal class EllipseToolExecutor : UpdateableChangeExecutor
+internal class EllipseToolExecutor : ShapeToolExecutor<EllipseToolViewModel>
 {
-    private int strokeWidth;
-    private SKColor fillColor;
-    private SKColor strokeColor;
-    private Guid memberGuid;
-    private bool drawOnMask;
-
-    private bool transforming = false;
-    private EllipseToolViewModel? ellipseTool;
-    private VecI startPos;
-    private RectI lastRect;
-
-    public override ExecutionState Start()
-    {
-        ColorsViewModel? colorsVM = ViewModelMain.Current?.ColorsSubViewModel;
-        ellipseTool = (EllipseToolViewModel?)(ViewModelMain.Current?.ToolsSubViewModel.GetTool<EllipseToolViewModel>());
-        BasicShapeToolbar? toolbar = (BasicShapeToolbar?)ellipseTool?.Toolbar;
-        ViewModels.SubViewModels.Document.StructureMemberViewModel? member = document?.SelectedStructureMember;
-        if (colorsVM is null || toolbar is null || member is null || ellipseTool is null)
-            return ExecutionState.Error;
-        drawOnMask = member.ShouldDrawOnMask;
-        if (drawOnMask && !member.HasMaskBindable)
-            return ExecutionState.Error;
-        if (!drawOnMask && member is not LayerViewModel)
-            return ExecutionState.Error;
-
-        fillColor = toolbar.Fill ? toolbar.FillColor.ToSKColor() : SKColors.Transparent;
-        startPos = controller!.LastPixelPosition;
-        strokeColor = colorsVM.PrimaryColor;
-        strokeWidth = toolbar.ToolSize;
-        memberGuid = member.GuidValue;
-
-        colorsVM.AddSwatch(strokeColor);
-        DrawEllipseOrCircle(startPos);
-        return ExecutionState.Success;
-    }
-
     private void DrawEllipseOrCircle(VecI curPos)
     {
         RectI rect = RectI.FromTwoPoints(startPos, curPos);
@@ -53,48 +14,18 @@ internal class EllipseToolExecutor : UpdateableChangeExecutor
         if (rect.Height == 0)
             rect.Height = 1;
 
-        if (ellipseTool!.DrawCircle)
+        if (toolViewModel!.DrawCircle)
             rect.Width = rect.Height = Math.Min(rect.Width, rect.Height);
         lastRect = rect;
 
         helpers!.ActionAccumulator.AddActions(new DrawEllipse_Action(memberGuid, rect, strokeColor, fillColor, strokeWidth, drawOnMask));
     }
 
-    public override void OnTransformMoved(ShapeCorners corners)
-    {
-        if (!transforming)
-            return;
+    protected override void DrawShape(VecI currentPos) => DrawEllipseOrCircle(currentPos);
 
-        helpers!.ActionAccumulator.AddActions(
-            new DrawEllipse_Action(memberGuid, (RectI)RectD.FromCenterAndSize(corners.RectCenter, corners.RectSize), strokeColor, fillColor, strokeWidth, drawOnMask));
-    }
+    protected override IAction TransformMovedAction(ShapeData data) =>
+        new DrawEllipse_Action(memberGuid, (RectI)RectD.FromCenterAndSize(data.Center, data.Size), strokeColor,
+            fillColor, strokeWidth, drawOnMask);
 
-    public override void OnTransformApplied()
-    {
-        helpers!.ActionAccumulator.AddFinishedActions(new EndDrawEllipse_Action());
-        document!.TransformViewModel.HideTransform();
-        onEnded?.Invoke(this);
-    }
-
-    public override void OnPixelPositionChange(VecI pos)
-    {
-        if (transforming)
-            return;
-        DrawEllipseOrCircle(pos);
-    }
-
-    public override void OnLeftMouseButtonUp()
-    {
-        if (transforming)
-            return;
-        transforming = true;
-        document!.TransformViewModel.ShowFixedAngleShapeTransform(new ShapeCorners(lastRect));
-    }
-    
-    public override void ForceStop()
-    {
-        if (transforming)
-            document!.TransformViewModel.HideTransform();
-        helpers!.ActionAccumulator.AddFinishedActions(new EndDrawEllipse_Action());
-    }
+    protected override IAction EndDrawAction() => new EndDrawEllipse_Action();
 }

+ 6 - 79
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/RectangleToolExecutor.cs

@@ -1,50 +1,11 @@
-using System.Windows.Input;
-using ChunkyImageLib.DataHolders;
-using PixiEditor.Models.Enums;
-using PixiEditor.ViewModels.SubViewModels.Document;
+using ChunkyImageLib.DataHolders;
+using PixiEditor.ChangeableDocument.Actions;
 using PixiEditor.ViewModels.SubViewModels.Tools.Tools;
-using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
-internal class RectangleToolExecutor : UpdateableChangeExecutor
+internal class RectangleToolExecutor : ShapeToolExecutor<RectangleToolViewModel>
 {
-    private int strokeWidth;
-    private SKColor fillColor;
-    private SKColor strokeColor;
-    private Guid memberGuid;
-    private bool drawOnMask;
-
-    private bool transforming = false;
-    private RectangleToolViewModel? rectangleTool;
-    private VecI startPos;
-    private RectI lastRect;
-
-    public override ExecutionState Start()
-    {
-        ColorsViewModel? colorsVM = ViewModelMain.Current?.ColorsSubViewModel;
-        rectangleTool = (RectangleToolViewModel?)(ViewModelMain.Current?.ToolsSubViewModel.GetTool<RectangleToolViewModel>());
-        BasicShapeToolbar? toolbar = (BasicShapeToolbar?)rectangleTool?.Toolbar;
-        StructureMemberViewModel? member = document?.SelectedStructureMember;
-        if (colorsVM is null || toolbar is null || member is null || rectangleTool is null)
-            return ExecutionState.Error;
-        drawOnMask = member.ShouldDrawOnMask;
-        if (drawOnMask && !member.HasMaskBindable)
-            return ExecutionState.Error;
-        if (!drawOnMask && member is not LayerViewModel)
-            return ExecutionState.Error;
-
-        fillColor = toolbar.Fill ? toolbar.FillColor.ToSKColor() : SKColors.Transparent;
-        startPos = controller!.LastPixelPosition;
-        strokeColor = colorsVM.PrimaryColor;
-        strokeWidth = toolbar.ToolSize;
-        memberGuid = member.GuidValue;
-
-        colorsVM.AddSwatch(strokeColor);
-        DrawRectangle(startPos);
-        return ExecutionState.Success;
-    }
-
     private void DrawRectangle(VecI curPos)
     {
         RectI rect = RectI.FromTwoPoints(startPos, curPos);
@@ -58,43 +19,9 @@ internal class RectangleToolExecutor : UpdateableChangeExecutor
         helpers!.ActionAccumulator.AddActions(new DrawRectangle_Action(memberGuid, new ShapeData(rect.Center, rect.Size, 0, strokeWidth, strokeColor, fillColor), drawOnMask));
     }
 
-    public override void OnTransformMoved(ShapeCorners corners)
-    {
-        if (!transforming)
-            return;
-
-        var rect = (RectI)RectD.FromCenterAndSize(corners.RectCenter, corners.RectSize);
-        
-        helpers!.ActionAccumulator.AddActions(
-            new DrawRectangle_Action(memberGuid, new ShapeData(rect.Center, rect.Size, corners.RectRotation, strokeWidth, strokeColor, fillColor), drawOnMask));
-    }
-
-    public override void OnTransformApplied()
-    {
-        helpers!.ActionAccumulator.AddFinishedActions(new EndDrawRectangle_Action());
-        document!.TransformViewModel.HideTransform();
-        onEnded?.Invoke(this);
-    }
+    protected override void DrawShape(VecI currentPos) => DrawRectangle(currentPos);
 
-    public override void OnPixelPositionChange(VecI pos)
-    {
-        if (transforming)
-            return;
-        DrawRectangle(pos);
-    }
+    protected override IAction TransformMovedAction(ShapeData data) => new DrawRectangle_Action(memberGuid, data, drawOnMask);
 
-    public override void OnLeftMouseButtonUp()
-    {
-        if (transforming)
-            return;
-        transforming = true;
-        document!.TransformViewModel.ShowFixedAngleShapeTransform(new ShapeCorners(lastRect));
-    }
-    
-    public override void ForceStop()
-    {
-        if (transforming)
-            document!.TransformViewModel.HideTransform();
-        helpers!.ActionAccumulator.AddFinishedActions(new EndDrawRectangle_Action());
-    }
+    protected override IAction EndDrawAction() => new EndDrawRectangle_Action();
 }

+ 97 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/ShapeToolExecutor.cs

@@ -0,0 +1,97 @@
+using ChunkyImageLib.DataHolders;
+using PixiEditor.ChangeableDocument.Actions;
+using PixiEditor.Models.Enums;
+using PixiEditor.ViewModels.SubViewModels.Document;
+using PixiEditor.ViewModels.SubViewModels.Tools;
+using PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
+
+namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
+
+#nullable enable
+
+internal abstract class ShapeToolExecutor<T> : UpdateableChangeExecutor where T : ShapeTool
+{
+    protected int strokeWidth;
+    protected SKColor fillColor;
+    protected SKColor strokeColor;
+    protected Guid memberGuid;
+    protected bool drawOnMask;
+
+    protected bool transforming = false;
+    protected T? toolViewModel;
+    protected VecI startPos;
+    protected RectI lastRect;
+    
+    public override ExecutionState Start()
+    {
+        ColorsViewModel? colorsVM = ViewModelMain.Current?.ColorsSubViewModel;
+        toolViewModel = ViewModelMain.Current?.ToolsSubViewModel.GetTool<T>();
+        BasicShapeToolbar? toolbar = (BasicShapeToolbar?)toolViewModel?.Toolbar;
+        StructureMemberViewModel? member = document?.SelectedStructureMember;
+        if (colorsVM is null || toolbar is null || member is null)
+            return ExecutionState.Error;
+        drawOnMask = member.ShouldDrawOnMask;
+        if (drawOnMask && !member.HasMaskBindable)
+            return ExecutionState.Error;
+        if (!drawOnMask && member is not LayerViewModel)
+            return ExecutionState.Error;
+
+        fillColor = toolbar.Fill ? toolbar.FillColor.ToSKColor() : SKColors.Transparent;
+        startPos = controller!.LastPixelPosition;
+        strokeColor = colorsVM.PrimaryColor;
+        strokeWidth = toolbar.ToolSize;
+        memberGuid = member.GuidValue;
+
+        colorsVM.AddSwatch(strokeColor);
+        DrawShape(startPos);
+        return ExecutionState.Success;
+    }
+
+    protected abstract void DrawShape(VecI currentPos);
+    protected abstract IAction TransformMovedAction(ShapeData data);
+    protected abstract IAction EndDrawAction();
+
+    public override void OnTransformMoved(ShapeCorners corners)
+    {
+        if (!transforming)
+            return;
+
+        var rect = (RectI)RectD.FromCenterAndSize(corners.RectCenter, corners.RectSize);
+
+        ShapeData shapeData = new ShapeData(rect.Center, rect.Size, corners.RectRotation, strokeWidth, strokeColor,
+            fillColor);
+        IAction drawAction = TransformMovedAction(shapeData);
+        
+        helpers!.ActionAccumulator.AddActions(drawAction);
+    }
+
+    public override void OnTransformApplied()
+    {
+        helpers!.ActionAccumulator.AddFinishedActions(EndDrawAction());
+        document!.TransformViewModel.HideTransform();
+        onEnded?.Invoke(this);
+    }
+
+    public override void OnPixelPositionChange(VecI pos)
+    {
+        if (transforming)
+            return;
+        
+        DrawShape(pos);
+    }
+
+    public override void OnLeftMouseButtonUp()
+    {
+        if (transforming)
+            return;
+        transforming = true;
+        document!.TransformViewModel.ShowFixedAngleShapeTransform(new ShapeCorners(lastRect));
+    }
+    
+    public override void ForceStop()
+    {
+        if (transforming)
+            document!.TransformViewModel.HideTransform();
+        helpers!.ActionAccumulator.AddFinishedActions(EndDrawAction());
+    }
+}

+ 3 - 0
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentViewModel.cs

@@ -303,7 +303,10 @@ internal class DocumentViewModel : NotifyableObject
     public void UsePenTool() => Helpers.ChangeController.TryStartUpdateableChange<PenToolExecutor>();
 
     public void UseRectangleTool() => Helpers.ChangeController.TryStartUpdateableChange<RectangleToolExecutor>();
+    
     public void UseEllipseTool() => Helpers.ChangeController.TryStartUpdateableChange<EllipseToolExecutor>();
+    
+    
 
     public void Undo()
     {

+ 2 - 2
src/PixiEditor/ViewModels/SubViewModels/Main/ToolsViewModel.cs

@@ -60,10 +60,10 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>
         }
     }
 
-    public ToolViewModel? GetTool<T>()
+    public T? GetTool<T>()
         where T : ToolViewModel
     {
-        return ToolSet?.Where(static tool => tool is T).FirstOrDefault();
+        return (T)ToolSet?.Where(static tool => tool is T).FirstOrDefault();
     }
 
     public void SetActiveTool<T>()

+ 3 - 3
src/PixiEditor/ViewModels/SubViewModels/Tools/Tools/LineToolViewModel.cs

@@ -7,11 +7,11 @@ namespace PixiEditor.ViewModels.SubViewModels.Tools.Tools;
 [Command.Tool(Key = Key.L)]
 internal class LineToolViewModel : ShapeTool
 {
-    private string defaltActionDisplay = "Click and move to draw a line. Hold Shift to draw an even one.";
+    private string defaultActionDisplay = "Click and move to draw a line. Hold Shift to draw an even one.";
 
     public LineToolViewModel()
     {
-        ActionDisplay = defaltActionDisplay;
+        ActionDisplay = defaultActionDisplay;
         Toolbar = new BasicToolbar();
     }
 
@@ -22,6 +22,6 @@ internal class LineToolViewModel : ShapeTool
         if (shiftIsDown)
             ActionDisplay = "Click and move mouse to draw an even line.";
         else
-            ActionDisplay = defaltActionDisplay;
+            ActionDisplay = defaultActionDisplay;
     }
 }