File indexing completed on 2024-06-23 04:28:11

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2006-2007 Thomas Zander <zander@kde.org>
0003  * SPDX-FileCopyrightText: 2007-2008 Jan Hambrecht <jaham@gmx.net>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 #include "ShapeRotateStrategy.h"
0009 #include "SelectionDecorator.h"
0010 
0011 #include <KoToolBase.h>
0012 #include <KoCanvasBase.h>
0013 #include <KoSelection.h>
0014 #include <KoPointerEvent.h>
0015 #include <KoShapeManager.h>
0016 #include <KoCanvasResourceProvider.h>
0017 #include <commands/KoShapeTransformCommand.h>
0018 
0019 #include <QPointF>
0020 #include <math.h>
0021 #include <klocalizedstring.h>
0022 
0023 ShapeRotateStrategy::ShapeRotateStrategy(KoToolBase *tool, KoSelection *selection, const QPointF &clicked, Qt::MouseButtons buttons)
0024     : KoInteractionStrategy(tool)
0025     , m_start(clicked)
0026 {
0027     /**
0028      * The outline of the selection should look as if it is also rotated, so we
0029      * add it to the transformed shapes list.
0030      */
0031     m_transformedShapesAndSelection = selection->selectedEditableShapes();
0032     m_transformedShapesAndSelection << selection;
0033 
0034     Q_FOREACH (KoShape *shape, m_transformedShapesAndSelection) {
0035         m_oldTransforms << shape->transformation();
0036     }
0037 
0038     KoFlake::AnchorPosition anchor = !(buttons & Qt::RightButton) ?
0039                 KoFlake::Center :
0040                 KoFlake::AnchorPosition(tool->canvas()->resourceManager()->resource(KoFlake::HotPosition).toInt());
0041 
0042     m_rotationCenter = selection->absolutePosition(anchor);
0043 
0044     tool->setStatusText(i18n("Press ALT to rotate in 45 degree steps."));
0045 }
0046 
0047 void ShapeRotateStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardModifiers modifiers)
0048 {
0049     qreal angle = atan2(point.y() - m_rotationCenter.y(), point.x() - m_rotationCenter.x()) -
0050                   atan2(m_start.y() - m_rotationCenter.y(), m_start.x() - m_rotationCenter.x());
0051     angle = angle / M_PI * 180;  // convert to degrees.
0052     if (modifiers & (Qt::AltModifier | Qt::ControlModifier)) {
0053         // limit to 45 degree angles
0054         qreal modula = qAbs(angle);
0055         while (modula > 45.0) {
0056             modula -= 45.0;
0057         }
0058         if (modula > 22.5) {
0059             modula -= 45.0;
0060         }
0061         angle += (angle > 0 ? -1 : 1) * modula;
0062     }
0063 
0064     rotateBy(angle);
0065 }
0066 
0067 void ShapeRotateStrategy::rotateBy(qreal angle)
0068 {
0069     QTransform matrix;
0070     matrix.translate(m_rotationCenter.x(), m_rotationCenter.y());
0071     matrix.rotate(angle);
0072     matrix.translate(-m_rotationCenter.x(), -m_rotationCenter.y());
0073 
0074     QTransform applyMatrix = matrix * m_rotationMatrix.inverted();
0075     m_rotationMatrix = matrix;
0076     Q_FOREACH (KoShape *shape, m_transformedShapesAndSelection) {
0077         QRectF dirtyRect = shape->boundingRect();
0078         shape->applyAbsoluteTransformation(applyMatrix);
0079         dirtyRect |= shape->boundingRect();
0080         shape->updateAbsolute(dirtyRect);
0081     }
0082 }
0083 
0084 void ShapeRotateStrategy::paint(QPainter &painter, const KoViewConverter &converter)
0085 {
0086     // paint the rotation center
0087     painter.setPen(QPen(Qt::red));
0088     painter.setBrush(QBrush(Qt::red));
0089     painter.setRenderHint(QPainter::Antialiasing, true);
0090     QRectF circle(0, 0, handleRadius(), handleRadius());
0091     circle.moveCenter(converter.documentToView(m_rotationCenter));
0092     painter.drawEllipse(circle);
0093 }
0094 
0095 KUndo2Command *ShapeRotateStrategy::createCommand()
0096 {
0097     QList<QTransform> newTransforms;
0098     Q_FOREACH (KoShape *shape, m_transformedShapesAndSelection) {
0099         newTransforms << shape->transformation();
0100     }
0101 
0102     KoShapeTransformCommand *cmd = new KoShapeTransformCommand(m_transformedShapesAndSelection, m_oldTransforms, newTransforms);
0103     cmd->setText(kundo2_i18n("Rotate"));
0104     return cmd;
0105 }