diff --git a/.gitignore b/.gitignore index 63d68f324..6dd4cfed8 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ po/Makefile.in.in po/POTFILES po/stamp-it xdg/pinta.desktop +.vs # Help help/*/*.mo diff --git a/Pinta.Core/Effects/Utility.cs b/Pinta.Core/Effects/Utility.cs index 69267d7a1..a9f92c038 100644 --- a/Pinta.Core/Effects/Utility.cs +++ b/Pinta.Core/Effects/Utility.cs @@ -639,5 +639,26 @@ public static int FastDivideShortByByte(ushort n, byte d) 0x80808081, 0x00000000, 39 // 255 }; - } + /// + /// Gets the nearest step angle in radians. + /// + /// The nearest step angle in radians. + /// Angle in radians. + /// Number of steps to divide the circle. + public static double GetNearestStepAngle (double angle, int steps) + { + double fullTurn = 2 * Math.PI; + double stepAngle = fullTurn / steps; + double normalizedAngle = angle % fullTurn; + int sector = Convert.ToInt32 (Math.Truncate ((normalizedAngle % fullTurn) / stepAngle)); + + var leftStepAngle = sector * stepAngle; + var rightStepAngle = (sector + 1) * stepAngle; + + if ((angle - leftStepAngle) < (rightStepAngle - angle)) + return leftStepAngle; + else + return rightStepAngle; + } + } } diff --git a/Pinta.Tools/Tools/BaseTransformTool.cs b/Pinta.Tools/Tools/BaseTransformTool.cs index 7c4a88e4b..69c79c167 100644 --- a/Pinta.Tools/Tools/BaseTransformTool.cs +++ b/Pinta.Tools/Tools/BaseTransformTool.cs @@ -31,19 +31,21 @@ namespace Pinta.Tools { public abstract class BaseTransformTool : BaseTool { - #region Members - private readonly Matrix transform = new Matrix(); + #region Members + private readonly int rotate_steps = 32; + private readonly Matrix transform = new Matrix(); private Rectangle source_rect; private PointD original_point; private bool is_dragging = false; private bool is_rotating = false; - #endregion - - #region Constructor - /// - /// Initializes a new instance of the class. - /// - public BaseTransformTool () + private bool rotateBySteps = false; + #endregion + + #region Constructor + /// + /// Initializes a new instance of the class. + /// + public BaseTransformTool () { } #endregion @@ -115,7 +117,10 @@ protected virtual void OnFinishTransform() if (is_rotating) { - transform.Translate(center.X, center.Y); + if (rotateBySteps) + angle = Utility.GetNearestStepAngle (angle, rotate_steps); + + transform.Translate(center.X, center.Y); transform.Rotate(-angle); transform.Translate(-center.X, -center.Y); } @@ -134,7 +139,17 @@ protected override void OnMouseUp (Gtk.DrawingArea canvas, Gtk.ButtonReleaseEven OnFinishTransform(); } - #endregion - } + + protected override void OnKeyDown (Gtk.DrawingArea canvas, Gtk.KeyPressEventArgs args) + { + rotateBySteps = (args.Event.Key == Gdk.Key.Shift_L); + } + + protected override void OnKeyUp (Gtk.DrawingArea canvas, Gtk.KeyReleaseEventArgs args) + { + rotateBySteps = false; + } + #endregion + } } diff --git a/Pinta.Tools/Tools/MoveSelectedTool.cs b/Pinta.Tools/Tools/MoveSelectedTool.cs index de241deba..b3ea06579 100644 --- a/Pinta.Tools/Tools/MoveSelectedTool.cs +++ b/Pinta.Tools/Tools/MoveSelectedTool.cs @@ -46,7 +46,7 @@ public class MoveSelectedTool : BaseTransformTool get { return "Tools.Move.png"; } } public override string StatusBarText { - get { return Catalog.GetString ("Left click and drag the selection to move selected content. Right click and drag the selection to rotate selected content."); } + get { return Catalog.GetString ("Left click and drag the selection to move selected content. Right click and drag the selection to rotate selected content. Hold Shift to rotate in steps."); } } public override Gdk.Cursor DefaultCursor { get { return new Gdk.Cursor (Gdk.Display.Default, PintaCore.Resources.GetIcon ("Tools.Move.png"), 0, 0); } diff --git a/Pinta.Tools/Tools/MoveSelectionTool.cs b/Pinta.Tools/Tools/MoveSelectionTool.cs index 35bdc6d65..923a5a91e 100644 --- a/Pinta.Tools/Tools/MoveSelectionTool.cs +++ b/Pinta.Tools/Tools/MoveSelectionTool.cs @@ -45,7 +45,7 @@ public class MoveSelectionTool : BaseTransformTool get { return "Tools.MoveSelection.png"; } } public override string StatusBarText { - get { return Catalog.GetString ("Left click and drag the selection to move selection outline. Right click and drag the selection to rotate selection outline."); } + get { return Catalog.GetString ("Left click and drag the selection to move selection outline. Right click and drag the selection to rotate selection outline. Hold Shift to rotate in steps."); } } public override Gdk.Cursor DefaultCursor { get { return new Gdk.Cursor (Gdk.Display.Default, PintaCore.Resources.GetIcon ("Tools.MoveSelection.png"), 0, 0); }