Krita Source Code Documentation
Loading...
Searching...
No Matches
KisZoomAndRotateAction Class Reference

This class handles both rotation and zooming operation. This is separate from Zoom and Rotate operation applied individually because the order of transformation is different. More...

#include <kis_zoom_and_rotate_action.h>

+ Inheritance diagram for KisZoomAndRotateAction:

Classes

class  Private
 

Public Types

enum  Shortcut { ContinuousRotateMode , DiscreteRotateMode }
 

Public Member Functions

void activate (int shortcut) override
 
void begin (int shortcut, QEvent *event) override
 
void cursorMovedAbsolute (const QPointF &lastPos, const QPointF &pos) override
 
void deactivate (int shortcut) override
 
KisInputActionGroup inputActionGroup (int shortcut) const override
 
void inputEvent (QEvent *event) override
 
 KisZoomAndRotateAction ()
 
int priority () const override
 
 ~KisZoomAndRotateAction ()
 
- Public Member Functions inherited from KisAbstractInputAction
virtual bool canIgnoreModifiers () const
 
virtual QString description () const
 
virtual void end (QEvent *event)
 
virtual QString id () const
 
virtual bool isAvailable () const
 
virtual bool isShortcutRequired (int shortcut) const
 
 KisAbstractInputAction (const QString &id)
 
virtual QString name () const
 
virtual QHash< QString, int > shortcutIndexes () const
 
virtual bool supportsHiResInputEvents (int shortcut) const
 
virtual ~KisAbstractInputAction ()
 

Private Member Functions

qreal canvasRotationAngle (QPointF p0, QPointF p1)
 

Private Attributes

const QScopedPointer< Privated
 

Additional Inherited Members

- Public Attributes inherited from KisAbstractInputAction
QString description
 
QString id
 
QHash< QString, int > indexes
 
QPointF lastCursorPosition
 
QString name
 
QPointF startCursorPosition
 
- Static Public Attributes inherited from KisAbstractInputAction
static KisInputManagerinputManager
 
- Protected Member Functions inherited from KisAbstractInputAction
virtual void cursorMoved (const QPointF &lastPos, const QPointF &pos)
 
QPoint eventPos (const QEvent *event)
 
QPointF eventPosF (const QEvent *event)
 
KisInputManagerinputManager () const
 
void setDescription (const QString &description)
 
void setName (const QString &name)
 
void setShortcutIndexes (const QHash< QString, int > &indexes)
 

Detailed Description

This class handles both rotation and zooming operation. This is separate from Zoom and Rotate operation applied individually because the order of transformation is different.

Definition at line 19 of file kis_zoom_and_rotate_action.h.

Member Enumeration Documentation

◆ Shortcut

Enumerator
ContinuousRotateMode 
DiscreteRotateMode 

Definition at line 22 of file kis_zoom_and_rotate_action.h.

Constructor & Destructor Documentation

◆ KisZoomAndRotateAction()

KisZoomAndRotateAction::KisZoomAndRotateAction ( )

Definition at line 35 of file kis_zoom_and_rotate_action.cpp.

36 : KisAbstractInputAction ("Zoom and Rotate Canvas")
37 , d(new Private)
38{
39 setName(i18n("Zoom and Rotate Canvas"));
40 QHash<QString, int> shortcuts;
41 shortcuts.insert(i18n("Rotate Mode"), ContinuousRotateMode);
42 shortcuts.insert(i18n("Discrete Rotate Mode"), DiscreteRotateMode);
43 setShortcutIndexes(shortcuts);
44}
KisAbstractInputAction(const QString &id)
void setShortcutIndexes(const QHash< QString, int > &indexes)
void setName(const QString &name)
const QScopedPointer< Private > d

References ContinuousRotateMode, DiscreteRotateMode, KisAbstractInputAction::setName(), and KisAbstractInputAction::setShortcutIndexes().

◆ ~KisZoomAndRotateAction()

KisZoomAndRotateAction::~KisZoomAndRotateAction ( )

Definition at line 46 of file kis_zoom_and_rotate_action.cpp.

47{
48}

Member Function Documentation

◆ activate()

void KisZoomAndRotateAction::activate ( int shortcut)
overridevirtual

The method is called when the action is yet to be started, that is, e.g. the user has pressed all the modifiers for the action but hasn't started painting yet. This method is a right place to show the user what is going to happen, e.g. change the cursor.

Reimplemented from KisAbstractInputAction.

Definition at line 55 of file kis_zoom_and_rotate_action.cpp.

56{
57 Q_UNUSED(shortcut);
58}

◆ begin()

void KisZoomAndRotateAction::begin ( int shortcut,
QEvent * event )
overridevirtual

Begin the action.

Parameters
shortcutThe index of the behaviour to trigger.
eventThe mouse event that has triggered this action. Is null for keyboard-activated actions.

Reimplemented from KisAbstractInputAction.

Definition at line 65 of file kis_zoom_and_rotate_action.cpp.

66{
67 QTouchEvent *touchEvent = dynamic_cast<QTouchEvent *>(event);
68
69 if (touchEvent && touchEvent->touchPoints().size() > 0) {
70 d->shortcutIndex = shortcut;
71 d->lastPosition = touchEvent->touchPoints().at(0).pos();
72 d->lastDistance = 0;
73 d->previousAngle = 0;
74 d->initialReferenceAngle = 0;
75 d->accumRotationAngle = 0;
76 d->actionStillPoint = inputManager()->canvas()->coordinatesConverter()->makeWidgetStillPoint(d->lastPosition);
77 }
78}
static KisInputManager * inputManager
KisCoordinatesConverter * coordinatesConverter
KoViewTransformStillPoint makeWidgetStillPoint(const QPointF &viewPoint) const override
Creates a still point that links the viewPoint of the widget to the corresponding point of the image.
KisCanvas2 * canvas() const

References KisInputManager::canvas(), KisCanvas2::coordinatesConverter, d, KisAbstractInputAction::inputManager, and KisCoordinatesConverter::makeWidgetStillPoint().

◆ canvasRotationAngle()

qreal KisZoomAndRotateAction::canvasRotationAngle ( QPointF p0,
QPointF p1 )
private

Definition at line 133 of file kis_zoom_and_rotate_action.cpp.

134{
135 const QPointF slope = p1 - p0;
136 const qreal currentAngle = std::atan2(slope.y(), slope.x());
137
138 switch (d->shortcutIndex) {
140 if (!d->previousAngle) {
141 d->previousAngle = currentAngle;
142 return 0;
143 }
144 qreal rotationAngle = (180 / M_PI) * (currentAngle - d->previousAngle);
145 d->previousAngle = currentAngle;
146
148 KisCanvasController *controller = static_cast<KisCanvasController *>(canvas->canvasController());
149 const qreal canvasAnglePostRotation = controller->rotation() + rotationAngle;
150 const qreal snapDelta = angleForSnapping(canvasAnglePostRotation);
151 // we snap the canvas to an angle that is a multiple of 45
152 if (abs(snapDelta) <= 2 && abs(d->accumRotationAngle) <= 2) {
153 // accumulate the relative angle of finger from the point when we started snapping
154 d->accumRotationAngle += rotationAngle;
155 rotationAngle = rotationAngle - snapDelta;
156 } else {
157 // snap the canvas out using the accumulated angle
158 rotationAngle += d->accumRotationAngle;
159 d->accumRotationAngle = 0;
160 }
161
162 return rotationAngle;
163 }
164 case DiscreteRotateMode: {
165 if (!d->initialReferenceAngle) {
166 d->initialReferenceAngle = currentAngle;
167 return 0;
168 }
169 qreal rotationAngle = 0;
170 const qreal relativeAngle = (180 / M_PI) * (currentAngle - d->initialReferenceAngle);
171 const qreal rotationThreshold = 15;
172
173 // if the canvas is moved in either direction with an angle greater than the threshold, we rotate the canvas in
174 // that direction by 15°.
175 if (std::abs(relativeAngle) >= rotationThreshold && std::abs(relativeAngle) <= (360 - rotationThreshold)) {
176 // set reference as currentAngle to check if we go beyond the threshold next time
177 d->initialReferenceAngle = currentAngle;
178
179 if (std::abs(relativeAngle) <= 180) {
180 rotationAngle = KisAlgebra2D::copysign(15.0, relativeAngle);
181 } else {
182 // if we're over 180, it means the canvas has to be rotated in the opposite direction of the current
183 // angle. E.g if the relative angle is +341° then we move the canvas by -15° (because the actual effect
184 // is 341 - 360 = -19° on the original theta).
185 rotationAngle = KisAlgebra2D::copysign(15.0, -relativeAngle);
186 }
187 }
188 return rotationAngle;
189 }
190 default:
191 qWarning() << "KisZoomAndRotateAction: Unrecognized shortcut" << d->shortcutIndex;
192 return 0;
193 }
194}
QPointF p0
QPointF p1
KoCanvasController * canvasController() const
#define M_PI
Definition kis_global.h:111
qreal angleForSnapping(qreal angle)
Point abs(const Point &pt)
T copysign(T x, T y)
KisCanvas2 * canvas

References angleForSnapping(), Private::canvas, KisInputManager::canvas(), KoCanvasBase::canvasController(), ContinuousRotateMode, KisAlgebra2D::copysign(), d, DiscreteRotateMode, KisAbstractInputAction::inputManager, M_PI, p0, p1, and KisCanvasController::rotation().

◆ cursorMovedAbsolute()

void KisZoomAndRotateAction::cursorMovedAbsolute ( const QPointF & lastPos,
const QPointF & pos )
overridevirtual

Reimplemented from KisAbstractInputAction.

Definition at line 80 of file kis_zoom_and_rotate_action.cpp.

81{
82}

◆ deactivate()

void KisZoomAndRotateAction::deactivate ( int shortcut)
overridevirtual

The method is called when the action is not a candidate for the starting anymore. The action should revert everything that was done in activate() method.

See also
activate()

Reimplemented from KisAbstractInputAction.

Definition at line 60 of file kis_zoom_and_rotate_action.cpp.

61{
62 Q_UNUSED(shortcut);
63}

◆ inputActionGroup()

KisInputActionGroup KisZoomAndRotateAction::inputActionGroup ( int shortcut) const
overridevirtual
Returns
the group of the action the specified shortcut belongs to

Reimplemented from KisAbstractInputAction.

Definition at line 127 of file kis_zoom_and_rotate_action.cpp.

128{
129 Q_UNUSED(shortcut);
131}
@ ViewTransformActionGroup

References ViewTransformActionGroup.

◆ inputEvent()

void KisZoomAndRotateAction::inputEvent ( QEvent * event)
overridevirtual

Process an input event.

By default handles MouseMove events and passes the data to a convenience cursorMoved() method

Parameters
eventAn event to process.

Reimplemented from KisAbstractInputAction.

Definition at line 93 of file kis_zoom_and_rotate_action.cpp.

94{
95 switch (event->type()) {
96 case QEvent::TouchUpdate: {
97 QTouchEvent *tevent = dynamic_cast<QTouchEvent *>(event);
98 if (tevent && tevent->touchPoints().size() > 1) {
99
100 const QPointF p0 = tevent->touchPoints().at(0).pos();
101 const QPointF p1 = tevent->touchPoints().at(1).pos();
102
103 const qreal rotationAngle = canvasRotationAngle(p0, p1);
104 const float dist = QLineF(p0, p1).length();
105 const float scaleDelta = qFuzzyCompare(1.0f, 1.0f + d->lastDistance) ? 1.f : dist / d->lastDistance;
106
108 KisCanvasController *controller = static_cast<KisCanvasController *>(canvas->canvasController());
109 const qreal newZoom = canvas->viewConverter()->zoom() * scaleDelta;
110 KoViewTransformStillPoint adjustedStillPoint = d->actionStillPoint;
111 adjustedStillPoint.second = p0;
112 controller->setZoom(KoZoomMode::ZOOM_CONSTANT, newZoom, adjustedStillPoint);
113 controller->rotateCanvas(rotationAngle, adjustedStillPoint);
114
115 d->lastPosition = p0;
116 d->lastDistance = dist;
117
118 return;
119 }
120 }
121 default:
122 break;
123 }
125}
virtual void inputEvent(QEvent *event)
const KoViewConverter * viewConverter() const override
void rotateCanvas(qreal angle, const std::optional< KoViewTransformStillPoint > &stillPoint, bool isNativeGesture=false)
qreal canvasRotationAngle(QPointF p0, QPointF p1)
void setZoom(KoZoomMode::Mode mode, qreal zoom) override
virtual void zoom(qreal *zoomX, qreal *zoomY) const
@ ZOOM_CONSTANT
zoom x %
Definition KoZoomMode.h:24
static bool qFuzzyCompare(half p1, half p2)

References Private::canvas, KisInputManager::canvas(), KoCanvasBase::canvasController(), canvasRotationAngle(), d, KisAbstractInputAction::inputEvent(), KisAbstractInputAction::inputManager, p0, p1, qFuzzyCompare(), KisCanvasController::rotateCanvas(), KoCanvasControllerWidget::setZoom(), KisCanvas2::viewConverter(), KoViewConverter::zoom(), and KoZoomMode::ZOOM_CONSTANT.

◆ priority()

int KisZoomAndRotateAction::priority ( ) const
overridevirtual

The priority for this action.

Priority determines how "important" the action is and is used to resolve conflicts when multiple actions can be activated.

Reimplemented from KisAbstractInputAction.

Definition at line 50 of file kis_zoom_and_rotate_action.cpp.

51{
52 return 5;
53}

Member Data Documentation

◆ d

const QScopedPointer<Private> KisZoomAndRotateAction::d
private

Definition at line 44 of file kis_zoom_and_rotate_action.h.


The documentation for this class was generated from the following files: