1 /*
2 * Copyright (c) 2007 Sven Langkamp <sven.langkamp@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "kis_tool_select_path.h"
20
21 #include <KoPathShape.h>
22
23 #include "kis_cursor.h"
24 #include "kis_image.h"
25 #include "kis_painter.h"
26 #include "kis_selection_options.h"
27 #include "kis_canvas_resource_provider.h"
28 #include "kis_canvas2.h"
29 #include "kis_pixel_selection.h"
30 #include "kis_selection_tool_helper.h"
31 #include <KisView.h>
32
33
KisToolSelectPath(KoCanvasBase * canvas)34 KisToolSelectPath::KisToolSelectPath(KoCanvasBase * canvas)
35 : KisToolSelectBase<KisDelegatedSelectPathWrapper>(canvas,
36 KisCursor::load("tool_polygonal_selection_cursor.png", 6, 6),
37 i18n("Select path"),
38 new __KisToolSelectPathLocalTool(canvas, this))
39 {
40 }
41
requestStrokeEnd()42 void KisToolSelectPath::requestStrokeEnd()
43 {
44 localTool()->endPathWithoutLastPoint();
45 }
46
requestStrokeCancellation()47 void KisToolSelectPath::requestStrokeCancellation()
48 {
49 localTool()->cancelPath();
50 }
51
52 // Install an event filter to catch right-click events.
53 // This code is duplicated in kis_tool_path.cc
eventFilter(QObject * obj,QEvent * event)54 bool KisToolSelectPath::eventFilter(QObject *obj, QEvent *event)
55 {
56 Q_UNUSED(obj);
57 if (event->type() == QEvent::MouseButtonPress ||
58 event->type() == QEvent::MouseButtonDblClick) {
59 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
60 if (mouseEvent->button() == Qt::RightButton && hasUserInteractionRunning()) {
61 localTool()->removeLastPoint();
62 return true;
63 }
64 } else if (event->type() == QEvent::TabletPress) {
65 QTabletEvent *tabletEvent = static_cast<QTabletEvent*>(event);
66 if (tabletEvent->button() == Qt::RightButton && hasUserInteractionRunning()) {
67 localTool()->removeLastPoint();
68 return true;
69 }
70 }
71 return false;
72 }
73
createOptionWidgets()74 QList<QPointer<QWidget> > KisToolSelectPath::createOptionWidgets()
75 {
76 QList<QPointer<QWidget> > widgetsList =
77 DelegatedSelectPathTool::createOptionWidgets();
78 QList<QPointer<QWidget> > filteredWidgets;
79 Q_FOREACH (QWidget* widget, widgetsList) {
80 if (widget->objectName() != "Stroke widget") {
81 filteredWidgets.push_back(widget);
82 }
83 }
84 return filteredWidgets;
85 }
86
beginPrimaryAction(KoPointerEvent * event)87 void KisDelegatedSelectPathWrapper::beginPrimaryAction(KoPointerEvent *event) {
88 DelegatedSelectPathTool::mousePressEvent(event);
89 }
90
continuePrimaryAction(KoPointerEvent * event)91 void KisDelegatedSelectPathWrapper::continuePrimaryAction(KoPointerEvent *event){
92 DelegatedSelectPathTool::mouseMoveEvent(event);
93 }
94
endPrimaryAction(KoPointerEvent * event)95 void KisDelegatedSelectPathWrapper::endPrimaryAction(KoPointerEvent *event) {
96 DelegatedSelectPathTool::mouseReleaseEvent(event);
97 }
98
beginPrimaryDoubleClickAction(KoPointerEvent * event)99 void KisDelegatedSelectPathWrapper::beginPrimaryDoubleClickAction(KoPointerEvent *event)
100 {
101 DelegatedSelectPathTool::mouseDoubleClickEvent(event);
102 }
103
mousePressEvent(KoPointerEvent * event)104 void KisDelegatedSelectPathWrapper::mousePressEvent(KoPointerEvent *event)
105 {
106 // this event will be forwarded using beginPrimaryAction
107 Q_UNUSED(event);
108 }
109
mouseMoveEvent(KoPointerEvent * event)110 void KisDelegatedSelectPathWrapper::mouseMoveEvent(KoPointerEvent *event)
111 {
112 DelegatedSelectPathTool::mouseMoveEvent(event);
113
114 // WARNING: the code is duplicated from KisToolPaint::requestUpdateOutline
115 KisCanvas2 * kiscanvas = dynamic_cast<KisCanvas2*>(canvas());
116 KisPaintingAssistantsDecorationSP decoration = kiscanvas->paintingAssistantsDecoration();
117 if (decoration && decoration->visible() && decoration->hasPaintableAssistants()) {
118 kiscanvas->updateCanvas();
119 }
120 }
121
mouseReleaseEvent(KoPointerEvent * event)122 void KisDelegatedSelectPathWrapper::mouseReleaseEvent(KoPointerEvent *event)
123 {
124 // this event will be forwarded using continuePrimaryAction
125 Q_UNUSED(event);
126 }
127
mouseDoubleClickEvent(KoPointerEvent * event)128 void KisDelegatedSelectPathWrapper::mouseDoubleClickEvent(KoPointerEvent *event)
129 {
130 // this event will be forwarded using endPrimaryAction
131 Q_UNUSED(event);
132 }
133
hasUserInteractionRunning() const134 bool KisDelegatedSelectPathWrapper::hasUserInteractionRunning() const
135 {
136 return localTool()->pathStarted();
137 }
138
139
__KisToolSelectPathLocalTool(KoCanvasBase * canvas,KisToolSelectPath * parentTool)140 __KisToolSelectPathLocalTool::__KisToolSelectPathLocalTool(KoCanvasBase * canvas, KisToolSelectPath* parentTool)
141 : KoCreatePathTool(canvas), m_selectionTool(parentTool)
142 {
143 setEnableClosePathShortcut(false);
144 }
145
paintPath(KoPathShape & pathShape,QPainter & painter,const KoViewConverter & converter)146 void __KisToolSelectPathLocalTool::paintPath(KoPathShape &pathShape, QPainter &painter, const KoViewConverter &converter)
147 {
148 Q_UNUSED(converter);
149 KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas());
150 if (!kisCanvas)
151 return;
152
153 QTransform matrix;
154 matrix.scale(kisCanvas->image()->xRes(), kisCanvas->image()->yRes());
155 matrix.translate(pathShape.position().x(), pathShape.position().y());
156 m_selectionTool->paintToolOutline(&painter, m_selectionTool->pixelToView(matrix.map(pathShape.outline())));
157 }
158
addPathShape(KoPathShape * pathShape)159 void __KisToolSelectPathLocalTool::addPathShape(KoPathShape* pathShape)
160 {
161 pathShape->normalize();
162 pathShape->close();
163
164 KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas());
165 if (!kisCanvas)
166 return;
167
168 KisImageWSP image = kisCanvas->image();
169
170 KisSelectionToolHelper helper(kisCanvas, kundo2_i18n("Select by Bezier Curve"));
171
172 const SelectionMode mode =
173 helper.tryOverrideSelectionMode(kisCanvas->viewManager()->selection(),
174 m_selectionTool->selectionMode(),
175 m_selectionTool->selectionAction());
176
177 if (mode == PIXEL_SELECTION) {
178
179 KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection());
180
181 KisPainter painter(tmpSel);
182 painter.setPaintColor(KoColor(Qt::black, tmpSel->colorSpace()));
183 painter.setFillStyle(KisPainter::FillStyleForegroundColor);
184 painter.setAntiAliasPolygonFill(m_selectionTool->antiAliasSelection());
185 painter.setStrokeStyle(KisPainter::StrokeStyleNone);
186
187 QTransform matrix;
188 matrix.scale(image->xRes(), image->yRes());
189 matrix.translate(pathShape->position().x(), pathShape->position().y());
190
191 QPainterPath path = matrix.map(pathShape->outline());
192 painter.fillPainterPath(path);
193 tmpSel->setOutlineCache(path);
194
195 helper.selectPixelSelection(tmpSel, m_selectionTool->selectionAction());
196
197 delete pathShape;
198 } else {
199 helper.addSelectionShape(pathShape, m_selectionTool->selectionAction());
200 }
201 }
202
resetCursorStyle()203 void KisToolSelectPath::resetCursorStyle()
204 {
205 if (selectionAction() == SELECTION_ADD) {
206 useCursor(KisCursor::load("tool_polygonal_selection_cursor_add.png", 6, 6));
207 } else if (selectionAction() == SELECTION_SUBTRACT) {
208 useCursor(KisCursor::load("tool_polygonal_selection_cursor_sub.png", 6, 6));
209 } else {
210 KisToolSelectBase<KisDelegatedSelectPathWrapper>::resetCursorStyle();
211 }
212 }
213
214
215