diff --git a/libs/ui/input/kis_rotate_canvas_action.cpp b/libs/ui/input/kis_rotate_canvas_action.cpp index 0f4c29fc8a..b5852172b2 100644 --- a/libs/ui/input/kis_rotate_canvas_action.cpp +++ b/libs/ui/input/kis_rotate_canvas_action.cpp @@ -1,192 +1,200 @@ /* This file is part of the KDE project * Copyright (C) 2012 Arjen Hiemstra * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_rotate_canvas_action.h" #include #include #include #include "kis_cursor.h" #include "kis_canvas_controller.h" #include #include "kis_input_manager.h" #include class KisRotateCanvasAction::Private { public: Private() : previousAngle(0) {} Shortcut mode; qreal previousAngle; qreal startRotation; qreal previousRotation; }; KisRotateCanvasAction::KisRotateCanvasAction() : KisAbstractInputAction("Rotate Canvas") , d(new Private()) { setName(i18n("Rotate Canvas")); setDescription(i18n("The Rotate Canvas action rotates the canvas.")); QHash shortcuts; shortcuts.insert(i18n("Rotate Mode"), RotateModeShortcut); shortcuts.insert(i18n("Discrete Rotate Mode"), DiscreteRotateModeShortcut); shortcuts.insert(i18n("Rotate Left"), RotateLeftShortcut); shortcuts.insert(i18n("Rotate Right"), RotateRightShortcut); shortcuts.insert(i18n("Reset Rotation"), RotateResetShortcut); setShortcutIndexes(shortcuts); } KisRotateCanvasAction::~KisRotateCanvasAction() { delete d; } int KisRotateCanvasAction::priority() const { return 3; } void KisRotateCanvasAction::activate(int shortcut) { if (shortcut == DiscreteRotateModeShortcut) { QApplication::setOverrideCursor(KisCursor::rotateCanvasDiscreteCursor()); } else /* if (shortcut == SmoothRotateModeShortcut) */ { QApplication::setOverrideCursor(KisCursor::rotateCanvasSmoothCursor()); } } void KisRotateCanvasAction::deactivate(int shortcut) { Q_UNUSED(shortcut); QApplication::restoreOverrideCursor(); } void KisRotateCanvasAction::begin(int shortcut, QEvent *event) { KisAbstractInputAction::begin(shortcut, event); d->previousAngle = 0; KisCanvasController *canvasController = dynamic_cast(inputManager()->canvas()->canvasController()); switch(shortcut) { case RotateModeShortcut: case DiscreteRotateModeShortcut: d->mode = (Shortcut)shortcut; d->startRotation = inputManager()->canvas()->rotationAngle(); d->previousRotation = 0; break; case RotateLeftShortcut: canvasController->rotateCanvasLeft15(); break; case RotateRightShortcut: canvasController->rotateCanvasRight15(); break; case RotateResetShortcut: canvasController->resetCanvasRotation(); break; } } void KisRotateCanvasAction::cursorMovedAbsolute(const QPointF &startPos, const QPointF &pos) { const KisCoordinatesConverter *converter = inputManager()->canvas()->coordinatesConverter(); const QPointF centerPoint = converter->flakeToWidget(converter->flakeCenterPoint()); const QPointF startPoint = startPos - centerPoint; const QPointF newPoint = pos - centerPoint; const qreal oldAngle = atan2(startPoint.y(), startPoint.x()); const qreal newAngle = atan2(newPoint.y(), newPoint.x()); qreal newRotation = (180 / M_PI) * (newAngle - oldAngle); if (d->mode == DiscreteRotateModeShortcut) { const qreal angleStep = 15; - newRotation = qRound(newRotation / angleStep) * angleStep; + + // avoid jumps at the beginning of the rotation action + if (qAbs(newRotation) > 0.5 * angleStep) { + const qreal currentCanvasRotation = converter->rotationAngle(); + const qreal desiredOffset = newRotation - d->previousRotation; + newRotation = qRound((currentCanvasRotation + desiredOffset) / angleStep) * angleStep - currentCanvasRotation + d->previousRotation; + } else { + newRotation = d->previousRotation; + } } KisCanvasController *canvasController = dynamic_cast(inputManager()->canvas()->canvasController()); canvasController->rotateCanvas(newRotation - d->previousRotation); d->previousRotation = newRotation; } void KisRotateCanvasAction::inputEvent(QEvent* event) { switch (event->type()) { case QEvent::NativeGesture: { QNativeGestureEvent *gevent = static_cast(event); KisCanvas2 *canvas = inputManager()->canvas(); KisCanvasController *controller = static_cast(canvas->canvasController()); const float angle = gevent->value(); QPoint widgetPos = canvas->canvasWidget()->mapFromGlobal(gevent->globalPos()); controller->rotateCanvas(angle, widgetPos); return; } case QEvent::TouchUpdate: { QTouchEvent *touchEvent = static_cast(event); if (touchEvent->touchPoints().count() != 2) break; QPointF p0 = touchEvent->touchPoints().at(0).pos(); QPointF p1 = touchEvent->touchPoints().at(1).pos(); // high school (y2 - y1) / (x2 - x1) QPointF slope = p1 - p0; qreal newAngle = atan2(slope.y(), slope.x()); if (!d->previousAngle) { d->previousAngle = newAngle; return; } qreal delta = (180 / M_PI) * (newAngle - d->previousAngle); KisCanvas2 *canvas = inputManager()->canvas(); KisCanvasController *controller = static_cast(canvas->canvasController()); controller->rotateCanvas(delta); d->previousAngle = newAngle; return; } default: break; } KisAbstractInputAction::inputEvent(event); } KisInputActionGroup KisRotateCanvasAction::inputActionGroup(int shortcut) const { Q_UNUSED(shortcut); return ViewTransformActionGroup; } bool KisRotateCanvasAction::supportsHiResInputEvents() const { return true; }