1 /* This file is part of the KDE project
2
3 Copyright (C) 2006-2007, 2010 Thomas Zander <zander@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "KoInteractionTool.h"
22 #include "KoInteractionTool_p.h"
23 #include "KoToolBase_p.h"
24 #include "KoPointerEvent.h"
25 #include "KoCanvasBase.h"
26
27 #include "kis_global.h"
28 #include "kis_assert.h"
29
30
KoInteractionTool(KoCanvasBase * canvas)31 KoInteractionTool::KoInteractionTool(KoCanvasBase *canvas)
32 : KoToolBase(*(new KoInteractionToolPrivate(this, canvas)))
33 {
34 }
35
~KoInteractionTool()36 KoInteractionTool::~KoInteractionTool()
37 {
38 }
39
paint(QPainter & painter,const KoViewConverter & converter)40 void KoInteractionTool::paint(QPainter &painter, const KoViewConverter &converter)
41 {
42 Q_D(KoInteractionTool);
43
44 if (d->currentStrategy) {
45 d->currentStrategy->paint(painter, converter);
46 } else {
47 Q_FOREACH (KoInteractionStrategyFactorySP factory, d->interactionFactories) {
48 // skip the rest of rendering if the factory asks for it
49 if (factory->paintOnHover(painter, converter)) break;
50 }
51 }
52 }
53
mousePressEvent(KoPointerEvent * event)54 void KoInteractionTool::mousePressEvent(KoPointerEvent *event)
55 {
56 Q_D(KoInteractionTool);
57 if (d->currentStrategy) { // possible if the user presses an extra mouse button
58 cancelCurrentStrategy();
59 return;
60 }
61 d->currentStrategy = createStrategyBase(event);
62 if (d->currentStrategy == 0)
63 event->ignore();
64 }
65
mouseMoveEvent(KoPointerEvent * event)66 void KoInteractionTool::mouseMoveEvent(KoPointerEvent *event)
67 {
68 Q_D(KoInteractionTool);
69 d->lastPoint = event->point;
70
71 if (d->currentStrategy) {
72 d->currentStrategy->handleMouseMove(d->lastPoint, event->modifiers());
73 } else {
74 Q_FOREACH (KoInteractionStrategyFactorySP factory, d->interactionFactories) {
75 // skip the rest of rendering if the factory asks for it
76 if (factory->hoverEvent(event)) return;
77 }
78
79 event->ignore();
80 }
81 }
82
mouseReleaseEvent(KoPointerEvent * event)83 void KoInteractionTool::mouseReleaseEvent(KoPointerEvent *event)
84 {
85 Q_D(KoInteractionTool);
86 if (d->currentStrategy) {
87 d->currentStrategy->finishInteraction(event->modifiers());
88 KUndo2Command *command = d->currentStrategy->createCommand();
89 if (command)
90 d->canvas->addCommand(command);
91 delete d->currentStrategy;
92 d->currentStrategy = 0;
93 repaintDecorations();
94 } else
95 event->ignore();
96 }
97
keyPressEvent(QKeyEvent * event)98 void KoInteractionTool::keyPressEvent(QKeyEvent *event)
99 {
100 Q_D(KoInteractionTool);
101 event->ignore();
102 if (d->currentStrategy &&
103 (event->key() == Qt::Key_Control ||
104 event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift ||
105 event->key() == Qt::Key_Meta)) {
106 d->currentStrategy->handleMouseMove(d->lastPoint, event->modifiers());
107 event->accept();
108 }
109 }
110
keyReleaseEvent(QKeyEvent * event)111 void KoInteractionTool::keyReleaseEvent(QKeyEvent *event)
112 {
113 Q_D(KoInteractionTool);
114
115 if (!d->currentStrategy) {
116 KoToolBase::keyReleaseEvent(event);
117 return;
118 }
119
120 if (event->key() == Qt::Key_Escape) {
121 cancelCurrentStrategy();
122 event->accept();
123 } else if (event->key() == Qt::Key_Control ||
124 event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift ||
125 event->key() == Qt::Key_Meta) {
126 d->currentStrategy->handleMouseMove(d->lastPoint, event->modifiers());
127 }
128 }
129
currentStrategy()130 KoInteractionStrategy *KoInteractionTool::currentStrategy()
131 {
132 Q_D(KoInteractionTool);
133 return d->currentStrategy;
134 }
135
cancelCurrentStrategy()136 void KoInteractionTool::cancelCurrentStrategy()
137 {
138 Q_D(KoInteractionTool);
139 if (d->currentStrategy) {
140 d->currentStrategy->cancelInteraction();
141 delete d->currentStrategy;
142 d->currentStrategy = 0;
143 }
144 }
145
createStrategyBase(KoPointerEvent * event)146 KoInteractionStrategy *KoInteractionTool::createStrategyBase(KoPointerEvent *event)
147 {
148 Q_D(KoInteractionTool);
149
150 Q_FOREACH (KoInteractionStrategyFactorySP factory, d->interactionFactories) {
151 KoInteractionStrategy *strategy = factory->createStrategy(event);
152 if (strategy) {
153 return strategy;
154 }
155 }
156
157 return createStrategy(event);
158 }
159
addInteractionFactory(KoInteractionStrategyFactory * factory)160 void KoInteractionTool::addInteractionFactory(KoInteractionStrategyFactory *factory)
161 {
162 Q_D(KoInteractionTool);
163
164 Q_FOREACH (auto f, d->interactionFactories) {
165 KIS_SAFE_ASSERT_RECOVER_RETURN(f->id() != factory->id());
166 }
167
168 d->interactionFactories.append(toQShared(factory));
169 std::sort(d->interactionFactories.begin(),
170 d->interactionFactories.end(),
171 KoInteractionStrategyFactory::compareLess);
172 }
173
removeInteractionFactory(const QString & id)174 void KoInteractionTool::removeInteractionFactory(const QString &id)
175 {
176 Q_D(KoInteractionTool);
177 QList<KoInteractionStrategyFactorySP>::iterator it =
178 d->interactionFactories.begin();
179
180 while (it != d->interactionFactories.end()) {
181 if ((*it)->id() == id) {
182 it = d->interactionFactories.erase(it);
183 } else {
184 ++it;
185 }
186 }
187 }
188
hasInteractioFactory(const QString & id)189 bool KoInteractionTool::hasInteractioFactory(const QString &id)
190 {
191 Q_D(KoInteractionTool);
192
193 Q_FOREACH (auto f, d->interactionFactories) {
194 if (f->id() == id) {
195 return true;
196 }
197 }
198
199 return false;
200 }
201
tryUseCustomCursor()202 bool KoInteractionTool::tryUseCustomCursor()
203 {
204 Q_D(KoInteractionTool);
205
206 Q_FOREACH (auto f, d->interactionFactories) {
207 if (f->tryUseCustomCursor()) {
208 return true;
209 }
210 }
211
212 return false;
213 }
214
KoInteractionTool(KoInteractionToolPrivate & dd)215 KoInteractionTool::KoInteractionTool(KoInteractionToolPrivate &dd)
216 : KoToolBase(dd)
217 {
218 }
219