diff --git a/.idea/.idea.Pinta/.idea/.gitignore b/.idea/.idea.Pinta/.idea/.gitignore new file mode 100644 index 0000000000..b23b929ada --- /dev/null +++ b/.idea/.idea.Pinta/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/projectSettingsUpdater.xml +/modules.xml +/.idea.Pinta.iml +/contentModel.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.Pinta/.idea/indexLayout.xml b/.idea/.idea.Pinta/.idea/indexLayout.xml new file mode 100644 index 0000000000..7b08163ceb --- /dev/null +++ b/.idea/.idea.Pinta/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Pinta/.idea/vcs.xml b/.idea/.idea.Pinta/.idea/vcs.xml new file mode 100644 index 0000000000..35eb1ddfbb --- /dev/null +++ b/.idea/.idea.Pinta/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Pinta.Core/Classes/Rectangle.cs b/Pinta.Core/Classes/Rectangle.cs index f360ef70e1..9bf9d4089a 100644 --- a/Pinta.Core/Classes/Rectangle.cs +++ b/Pinta.Core/Classes/Rectangle.cs @@ -53,7 +53,7 @@ public RectangleD (in PointD point, double width, double height) /// /// /// Flips the start and end points if necessary to produce a rectangle with positive width and height. - /// Otherwise, a negative width or height is clamped to zero. + /// Otherwise, a negative width or height is allowed. /// public static RectangleD FromPoints (in PointD start, in PointD end, bool invert_if_negative = true) { @@ -63,9 +63,9 @@ public static RectangleD FromPoints (in PointD start, in PointD end, bool invert double x1 = Math.Min (start.X, end.X); double x2 = Math.Max (start.X, end.X); return new RectangleD (x1, y1, x2 - x1, y2 - y1); - } else { - return new RectangleD (start.X, start.Y, end.X - start.X, end.Y - start.Y); } + + return new RectangleD (start.X, start.Y, end.X - start.X, end.Y - start.Y); } public static readonly RectangleD Zero; diff --git a/Pinta.Tools/Handles/RectangleHandle.cs b/Pinta.Tools/Handles/RectangleHandle.cs index c6df2794fa..52c6da8cf5 100644 --- a/Pinta.Tools/Handles/RectangleHandle.cs +++ b/Pinta.Tools/Handles/RectangleHandle.cs @@ -18,7 +18,9 @@ public class RectangleHandle : IToolHandle private readonly MoveHandle[] handles = new MoveHandle[8]; private MoveHandle? active_handle = null; private PointD? drag_start_pos = null; + private PointD drag_offset_from_handle = PointD.Zero; private double aspect_ratio = 1; + public Matrix Transform { get; set; } = CairoExtensions.CreateIdentityMatrix (); public RectangleHandle () { @@ -87,6 +89,11 @@ public RectangleD Rectangle { } } + /// + /// Corrects the rectangle if the point meant to be the bottom right corner is above or to the left of the point meant to be the top left corner. + /// + public void CorrectRectangle () => Rectangle = RectangleD.FromPoints (start_pt, end_pt); + /// /// Begins a drag operation if the mouse position is on top of a handle. /// Mouse movements are clamped to fall within the specified image size. @@ -106,6 +113,7 @@ public bool BeginDrag (in PointD canvas_pos, in Size image_size) return false; drag_start_pos = view_pos; + drag_offset_from_handle = new PointD (canvas_pos.X - active_handle.CanvasPosition.X, canvas_pos.Y - active_handle.CanvasPosition.Y); return true; } @@ -121,8 +129,8 @@ public RectangleI UpdateDrag (PointD canvas_pos, ConstrainType constrain = Const // Clamp mouse position to the image size. canvas_pos = new PointD ( - Math.Round (Math.Clamp (canvas_pos.X, 0, image_size.Width)), - Math.Round (Math.Clamp (canvas_pos.Y, 0, image_size.Height))); + Math.Round (Math.Clamp (canvas_pos.X - drag_offset_from_handle.X, 0, image_size.Width)), + Math.Round (Math.Clamp (canvas_pos.Y - drag_offset_from_handle.Y, 0, image_size.Height))); var dirty = InvalidateRect; @@ -162,7 +170,6 @@ public void EndDrag () var rect = Rectangle; start_pt = rect.Location (); end_pt = rect.EndLocation (); - Console.WriteLine($"Start: {start_pt}, End: {end_pt}"); } /// @@ -171,7 +178,7 @@ public void EndDrag () public string? GetCursorAtPoint (PointD view_pos) => handles.FirstOrDefault (c => c.ContainsPoint (view_pos))?.CursorName; - private void UpdateHandlePositions () + public void UpdateHandlePositions () { var rect = Rectangle; var center = rect.GetCenter (); @@ -183,6 +190,12 @@ private void UpdateHandlePositions () handles[5].CanvasPosition = new PointD (center.X, rect.Top); handles[6].CanvasPosition = new PointD (rect.Right, center.Y); handles[7].CanvasPosition = new PointD (center.X, rect.Bottom); + foreach (var handle in handles) { + double x = handle.CanvasPosition.X; + double y = handle.CanvasPosition.Y; + Transform.TransformPoint (ref x, ref y); + handle.CanvasPosition = new PointD (x, y); + } } private void UpdateHandleUnderPoint (PointD view_pos) @@ -193,13 +206,11 @@ private void UpdateHandleUnderPoint (PointD view_pos) // at the same position so pick the bottom right corner. var rect = Rectangle; if (active_handle is not null && rect.Width == 0.0 && rect.Height == 0.0) - active_handle = handles[3]; + active_handle = handles[(int)HandleIndex.BottomRight]; } private void MoveActiveHandle (double x, double y, ConstrainType constrain = ConstrainType.None) { - // Update the rectangle's size depending on which handle was dragged. - Console.WriteLine((HandleIndex)Array.IndexOf (handles, active_handle)); switch ((HandleIndex)Array.IndexOf (handles, active_handle)) { case HandleIndex.TopLeft: start_pt = new (x, y); diff --git a/Pinta.Tools/Tools/BaseTransformTool.cs b/Pinta.Tools/Tools/BaseTransformTool.cs index 8bddd68ea6..0ccfd23410 100644 --- a/Pinta.Tools/Tools/BaseTransformTool.cs +++ b/Pinta.Tools/Tools/BaseTransformTool.cs @@ -37,6 +37,7 @@ public abstract class BaseTransformTool : BaseTool { private readonly int rotate_steps = 32; private readonly Matrix transform = CairoExtensions.CreateIdentityMatrix (); + private Matrix stored_handle_transform = CairoExtensions.CreateIdentityMatrix (); private RectangleD source_rect; private PointD original_point; private PointD rect_original_point; @@ -106,6 +107,7 @@ protected override void OnMouseMove (Document document, ToolMouseEventArgs e) var constrain = e.IsShiftPressed; transform.InitIdentity (); + rect_handle.Transform.InitMatrix (stored_handle_transform); if (is_scaling) { rect_handle.UpdateDrag (e.PointDouble, constrain ? ConstrainType.AspectRatio : ConstrainType.None); @@ -115,6 +117,7 @@ protected override void OnMouseMove (Document document, ToolMouseEventArgs e) var sx = (source_rect.Width > 0) ? (target_rect.Width / source_rect.Width) : 0.0; var sy = (source_rect.Height > 0) ? (target_rect.Height / source_rect.Height) : 0.0; + //transform.Multiply (rect_handle.Transform); transform.Translate (target_rect.Left, target_rect.Top); transform.Scale (sx, sy); transform.Translate (-source_rect.Left, -source_rect.Top); @@ -136,8 +139,11 @@ protected override void OnMouseMove (Document document, ToolMouseEventArgs e) transform.Translate (center.X, center.Y); transform.Rotate (-angle); transform.Translate (-center.X, -center.Y); - //TODO: the handle should rotate with the selection rather than just resizing to fit the new bounds - rect_handle.Rectangle = document.Selection.SelectionPath.GetBounds ().ToDouble (); + + rect_handle.Transform.Translate (center.X, center.Y); + rect_handle.Transform.Rotate (-angle); + rect_handle.Transform.Translate (-center.X, -center.Y); + rect_handle.UpdateHandlePositions (); } else { // The cursor position can be a subpixel value. Round to an integer // so that we only translate by entire pixels. @@ -145,7 +151,8 @@ protected override void OnMouseMove (Document document, ToolMouseEventArgs e) var dx = Math.Floor (e.PointDouble.X - original_point.X); var dy = Math.Floor (e.PointDouble.Y - original_point.Y); transform.Translate (dx, dy); - rect_handle.Rectangle = new RectangleD(rect_original_point.X + dx, rect_original_point.Y + dy, rect_handle.Rectangle.Width, rect_handle.Rectangle.Height); + rect_handle.Transform.Translate (dx, dy); + rect_handle.UpdateHandlePositions (); } OnUpdateTransform (document, transform); @@ -215,6 +222,7 @@ protected virtual void OnStartTransform (Document document) { source_rect = GetSourceRectangle (document); transform.InitIdentity (); + stored_handle_transform.InitMatrix (rect_handle.Transform); } protected virtual void OnUpdateTransform (Document document, Matrix transform) @@ -227,6 +235,8 @@ protected virtual void OnFinishTransform (Document document, Matrix transform) is_rotating = false; is_scaling = false; using_mouse = false; + + stored_handle_transform.Multiply (rect_handle.Transform); } protected override void OnAfterUndo (Document document) @@ -256,6 +266,8 @@ private void HandleSourceRectangleChanged (Document document) { var dirty = rect_handle.InvalidateRect; rect_handle.Rectangle = GetSourceRectangle (document); + rect_handle.Transform.InitIdentity (); + rect_handle.UpdateHandlePositions (); dirty = dirty.Union (rect_handle.InvalidateRect); PintaCore.Workspace.InvalidateWindowRect (dirty); } diff --git a/Pinta.Tools/Tools/MoveSelectedTool.cs b/Pinta.Tools/Tools/MoveSelectedTool.cs index e16fd1414d..7a96e0d1ae 100644 --- a/Pinta.Tools/Tools/MoveSelectedTool.cs +++ b/Pinta.Tools/Tools/MoveSelectedTool.cs @@ -126,7 +126,7 @@ protected override void OnFinishTransform (Document document, Matrix transform) if (hist != null) document.History.PushNewItem (hist); - rect_handle.Rectangle = RectangleD.FromPoints (rect_handle.Rectangle.Location (), rect_handle.Rectangle.EndLocation ()); + rect_handle.CorrectRectangle(); hist = null; original_selection = null; diff --git a/Pinta.Tools/Tools/MoveSelectionTool.cs b/Pinta.Tools/Tools/MoveSelectionTool.cs index fc772b53e8..65c85d22e2 100644 --- a/Pinta.Tools/Tools/MoveSelectionTool.cs +++ b/Pinta.Tools/Tools/MoveSelectionTool.cs @@ -36,7 +36,6 @@ public sealed class MoveSelectionTool : BaseTransformTool public MoveSelectionTool (IServiceManager service) : base (service) { - rect_handle.InvertIfNegative = true; } public override string Name => Translations.GetString ("Move Selection"); diff --git a/Pinta.Tools/Tools/SelectTool.cs b/Pinta.Tools/Tools/SelectTool.cs index 9f2e872b67..213705156c 100644 --- a/Pinta.Tools/Tools/SelectTool.cs +++ b/Pinta.Tools/Tools/SelectTool.cs @@ -233,8 +233,7 @@ private void AfterSelectionChange (object? sender, EventArgs event_args) /// private void LoadFromDocument (Document document) { - var selection = document.Selection; - handle.Rectangle = RectangleD.FromPoints (selection.Origin, selection.End); + handle.Rectangle = document.Selection.SelectionPath.GetBounds ().ToDouble (); ShowHandles (document.Selection.Visible && tools.CurrentTool == this); } }