1 /* This file is part of the KDE project
2 
3    Copyright (C) 2006 Thorsten Zachmann <zachmann@kde.org>
4    Copyright (C) 2006-2007 Thomas Zander <zander@kde.org>
5 
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10 
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.LIB.  If not, write to
18    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20 */
21 
22 #include "ShapeMoveStrategy.h"
23 #include "SelectionDecorator.h"
24 
25 #include <KoCanvasBase.h>
26 #include <KoShapeManager.h>
27 #include <KoShapeContainer.h>
28 #include <KoShapeContainerModel.h>
29 #include <KoCanvasResourceProvider.h>
30 #include <commands/KoShapeMoveCommand.h>
31 #include <KoSnapGuide.h>
32 #include <KoPointerEvent.h>
33 #include <KoToolBase.h>
34 #include <KoSelection.h>
35 #include <klocalizedstring.h>
36 #include <kis_global.h>
37 
38 #include "kis_debug.h"
39 
ShapeMoveStrategy(KoToolBase * tool,KoSelection * selection,const QPointF & clicked)40 ShapeMoveStrategy::ShapeMoveStrategy(KoToolBase *tool, KoSelection *selection, const QPointF &clicked)
41     : KoInteractionStrategy(tool)
42     , m_start(clicked)
43     , m_canvas(tool->canvas())
44 {
45     QList<KoShape *> selectedShapes = selection->selectedEditableShapes();
46 
47     Q_FOREACH (KoShape *shape, selectedShapes) {
48         m_selectedShapes << shape;
49         m_previousPositions << shape->absolutePosition(KoFlake::Center);
50         m_newPositions << shape->absolutePosition(KoFlake::Center);
51     }
52 
53     KoFlake::AnchorPosition anchor =
54             KoFlake::AnchorPosition(
55                 m_canvas->resourceManager()->resource(KoFlake::HotPosition).toInt());
56 
57     m_initialOffset = selection->absolutePosition(anchor) - m_start;
58     m_canvas->snapGuide()->setIgnoredShapes(KoShape::linearizeSubtree(m_selectedShapes));
59 
60     tool->setStatusText(i18n("Press Shift to hold x- or y-position."));
61 }
62 
handleMouseMove(const QPointF & point,Qt::KeyboardModifiers modifiers)63 void ShapeMoveStrategy::handleMouseMove(const QPointF &point, Qt::KeyboardModifiers modifiers)
64 {
65     if (m_selectedShapes.isEmpty()) {
66         return;
67     }
68     QPointF diff = point - m_start;
69 
70     if (modifiers & Qt::ShiftModifier) {
71         // Limit change to one direction only
72         diff = snapToClosestAxis(diff);
73     } else {
74         QPointF positionToSnap = point + m_initialOffset;
75         QPointF snappedPosition = tool()->canvas()->snapGuide()->snap(positionToSnap, modifiers);
76         diff = snappedPosition - m_initialOffset - m_start;
77     }
78 
79     moveSelection(diff);
80     m_finalMove = diff;
81 }
82 
moveSelection(const QPointF & diff)83 void ShapeMoveStrategy::moveSelection(const QPointF &diff)
84 {
85     Q_ASSERT(m_newPositions.count());
86 
87     int i = 0;
88     Q_FOREACH (KoShape *shape, m_selectedShapes) {
89         QPointF delta = m_previousPositions.at(i) + diff - shape->absolutePosition(KoFlake::Center);
90         if (shape->parent()) {
91             shape->parent()->model()->proposeMove(shape, delta);
92         }
93         tool()->canvas()->clipToDocument(shape, delta);
94         QPointF newPos(shape->absolutePosition(KoFlake::Center) + delta);
95         m_newPositions[i] = newPos;
96 
97         const QRectF oldDirtyRect = shape->boundingRect();
98         shape->setAbsolutePosition(newPos, KoFlake::Center);
99         shape->updateAbsolute(oldDirtyRect | oldDirtyRect.translated(delta));
100         i++;
101     }
102 }
103 
createCommand()104 KUndo2Command *ShapeMoveStrategy::createCommand()
105 {
106     tool()->canvas()->snapGuide()->reset();
107     if (m_finalMove.isNull()) {
108         return 0;
109     }
110     return new KoShapeMoveCommand(m_selectedShapes, m_previousPositions, m_newPositions);
111 }
112 
finishInteraction(Qt::KeyboardModifiers modifiers)113 void ShapeMoveStrategy::finishInteraction(Qt::KeyboardModifiers modifiers)
114 {
115     Q_UNUSED(modifiers);
116 }
117 
paint(QPainter & painter,const KoViewConverter & converter)118 void ShapeMoveStrategy::paint(QPainter &painter, const KoViewConverter &converter)
119 {
120     Q_UNUSED(painter);
121     Q_UNUSED(converter);
122 }
123