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

0001 /* This file is part of the KDE project
0002 
0003    SPDX-FileCopyrightText: 2006 Thorsten Zachmann <zachmann@kde.org>
0004    SPDX-FileCopyrightText: 2006-2007 Thomas Zander <zander@kde.org>
0005 
0006    SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "ShapeMoveStrategy.h"
0010 #include "SelectionDecorator.h"
0011 
0012 #include <KoCanvasBase.h>
0013 #include <KoShapeManager.h>
0014 #include <KoShapeContainer.h>
0015 #include <KoShapeContainerModel.h>
0016 #include <KoCanvasResourceProvider.h>
0017 #include <commands/KoShapeMoveCommand.h>
0018 #include <KoSnapGuide.h>
0019 #include <KoPointerEvent.h>
0020 #include <KoToolBase.h>
0021 #include <KoSelection.h>
0022 #include <klocalizedstring.h>
0023 #include <kis_global.h>
0024 
0025 #include "kis_debug.h"
0026 
0027 ShapeMoveStrategy::ShapeMoveStrategy(KoToolBase *tool, KoSelection *selection, const QPointF &clicked)
0028     : KoInteractionStrategy(tool)
0029     , m_start(clicked)
0030     , m_canvas(tool->canvas())
0031 {
0032     QList<KoShape *> selectedShapes = selection->selectedEditableShapes();
0033 
0034     Q_FOREACH (KoShape *shape, selectedShapes) {
0035         m_selectedShapes << shape;
0036         m_previousPositions << shape->absolutePosition(KoFlake::Center);
0037         m_newPositions << shape->absolutePosition(KoFlake::Center);
0038     }
0039 
0040     KoFlake::AnchorPosition anchor =
0041             KoFlake::AnchorPosition(
0042                 m_canvas->resourceManager()->resource(KoFlake::HotPosition).toInt());
0043 
0044     m_initialOffset = selection->absolutePosition(anchor) - m_start;
0045     m_canvas->snapGuide()->setIgnoredShapes(KoShape::linearizeSubtree(m_selectedShapes));
0046 
0047     tool->setStatusText(i18n("Press Shift to hold x- or y-position."));
0048 }
0049 
0050 void ShapeMoveStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardModifiers modifiers)
0051 {
0052     if (m_selectedShapes.isEmpty()) {
0053         return;
0054     }
0055     QPointF diff = point - m_start;
0056 
0057     if (modifiers & Qt::ShiftModifier) {
0058         // Limit change to one direction only
0059         diff = snapToClosestAxis(diff);
0060     } else {
0061         QPointF positionToSnap = point + m_initialOffset;
0062         QPointF snappedPosition = tool()->canvas()->snapGuide()->snap(positionToSnap, modifiers);
0063         diff = snappedPosition - m_initialOffset - m_start;
0064     }
0065 
0066     moveSelection(diff);
0067     m_finalMove = diff;
0068 }
0069 
0070 void ShapeMoveStrategy::moveSelection(const QPointF &diff)
0071 {
0072     Q_ASSERT(m_newPositions.count());
0073 
0074     int i = 0;
0075     Q_FOREACH (KoShape *shape, m_selectedShapes) {
0076         QPointF delta = m_previousPositions.at(i) + diff - shape->absolutePosition(KoFlake::Center);
0077         if (shape->parent()) {
0078             shape->parent()->model()->proposeMove(shape, delta);
0079         }
0080         tool()->canvas()->clipToDocument(shape, delta);
0081         QPointF newPos(shape->absolutePosition(KoFlake::Center) + delta);
0082         m_newPositions[i] = newPos;
0083 
0084         const QRectF oldDirtyRect = shape->boundingRect();
0085         shape->setAbsolutePosition(newPos, KoFlake::Center);
0086         shape->updateAbsolute(oldDirtyRect | oldDirtyRect.translated(delta));
0087         i++;
0088     }
0089 }
0090 
0091 KUndo2Command *ShapeMoveStrategy::createCommand()
0092 {
0093     tool()->canvas()->snapGuide()->reset();
0094     if (m_finalMove.isNull()) {
0095         return 0;
0096     }
0097     return new KoShapeMoveCommand(m_selectedShapes, m_previousPositions, m_newPositions);
0098 }
0099 
0100 void ShapeMoveStrategy::finishInteraction(Qt::KeyboardModifiers modifiers)
0101 {
0102     Q_UNUSED(modifiers);
0103 }
0104 
0105 void ShapeMoveStrategy::paint(QPainter &painter, const KoViewConverter &converter)
0106 {
0107     Q_UNUSED(painter);
0108     Q_UNUSED(converter);
0109 }