Browse Source

Keep selection in document area #520

CPKreuz 2 years ago
parent
commit
cc878daee0

+ 8 - 2
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectEllipse_UpdateableChange.cs

@@ -7,6 +7,7 @@ namespace PixiEditor.ChangeableDocument.Changes.Selection;
 internal class SelectEllipse_UpdateableChange : UpdateableChange
 {
     private RectI borders;
+    private VectorPath? documentConstraint;
     private readonly SelectionMode mode;
     private VectorPath? originalPath;
 
@@ -26,6 +27,8 @@ internal class SelectEllipse_UpdateableChange : UpdateableChange
     public override bool InitializeAndValidate(Document target)
     {
         originalPath = new VectorPath(target.Selection.SelectionPath);
+        documentConstraint = new VectorPath();
+        documentConstraint.AddRect(new RectI(VecI.Zero, target.Size));
         return true;
     }
 
@@ -35,11 +38,13 @@ internal class SelectEllipse_UpdateableChange : UpdateableChange
         if (!borders.IsZeroArea)
             ellipsePath.AddOval(borders);
 
+        using var inConstraint = ellipsePath.Op(documentConstraint!, VectorPathOp.Intersect);
+
         var toDispose = target.Selection.SelectionPath;
         if (mode == SelectionMode.New)
-            target.Selection.SelectionPath = new(ellipsePath);
+            target.Selection.SelectionPath = new(inConstraint);
         else
-            target.Selection.SelectionPath = originalPath!.Op(ellipsePath, mode.ToVectorPathOp());
+            target.Selection.SelectionPath = originalPath!.Op(inConstraint, mode.ToVectorPathOp());
         toDispose.Dispose();
 
         return new Selection_ChangeInfo(new VectorPath(target.Selection.SelectionPath));
@@ -67,5 +72,6 @@ internal class SelectEllipse_UpdateableChange : UpdateableChange
     public override void Dispose()
     {
         originalPath?.Dispose();
+        documentConstraint?.Dispose();
     }
 }

+ 6 - 2
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectLasso_UpdateableChange.cs

@@ -5,6 +5,8 @@ using PixiEditor.DrawingApi.Core.Surface.Vector;
 namespace PixiEditor.ChangeableDocument.Changes.Selection;
 internal class SelectLasso_UpdateableChange : UpdateableChange
 {
+    private RectI constraint;
+    private VecI initialPoint;
     private VectorPath? originalPath;
     private VectorPath path = new() { FillType = PathFillType.EvenOdd };
     private readonly SelectionMode mode;
@@ -12,18 +14,20 @@ internal class SelectLasso_UpdateableChange : UpdateableChange
     [GenerateUpdateableChangeActions]
     public SelectLasso_UpdateableChange(VecI point, SelectionMode mode)
     {
-        path.MoveTo(point);
+        initialPoint = point;
         this.mode = mode;
     }
 
     [UpdateChangeMethod]
     public void Update(VecI point)
     {
-        path.LineTo(point);
+        path.LineTo(point.KeepInside(constraint));
     }
 
     public override bool InitializeAndValidate(Document target)
     {
+        constraint = new RectI(VecI.Zero, target.Size);
+        path.MoveTo(initialPoint.KeepInside(constraint));
         originalPath = new VectorPath(target.Selection.SelectionPath);
         return true;
     }

+ 5 - 4
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectRectangle_UpdateableChange.cs

@@ -33,10 +33,11 @@ internal class SelectRectangle_UpdateableChange : UpdateableChange
         using var rectPath = new VectorPath() { FillType = PathFillType.EvenOdd };
         if (!rect.IsZeroArea)
         {
-            rectPath.MoveTo(rect.TopLeft);
-            rectPath.LineTo(rect.TopRight);
-            rectPath.LineTo(rect.BottomRight);
-            rectPath.LineTo(rect.BottomLeft);
+            var constrained = rect.Intersect(new RectI(VecI.Zero, target.Size));
+            rectPath.MoveTo(constrained.TopLeft);
+            rectPath.LineTo(constrained.TopRight);
+            rectPath.LineTo(constrained.BottomRight);
+            rectPath.LineTo(constrained.BottomLeft);
             rectPath.Close();
         }
 

+ 5 - 0
src/PixiEditor.DrawingApi.Core/Numerics/VecI.cs

@@ -69,6 +69,11 @@ public struct VecI : IEquatable<VecI>
         return new(X, 2 * lineY - Y);
     }
 
+    public VecI KeepInside(RectI rect)
+    {
+        return new VecI(Math.Clamp(X, rect.Left, rect.Right), Math.Clamp(Y, rect.Top, rect.Bottom));
+    }
+
     public byte[] ToByteArray()
     {
         var data = new byte[sizeof(int) * 2];