Commit 5f45d3d3 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

Added easy finishing to Path and Select Path tools

Now you can finish the path:
1) By double clicking on the canvas
2) By clicking on the first point
3) By pressing Enter key
4) By Shift + Click

You can cancel the path:
1) By pressing Esc key

BUG:322328
REVIEW:112405
parent d30f355f
......@@ -20,103 +20,35 @@
#include "kis_tool_path.h"
#include <KoPathShape.h>
#include <KoCanvasBase.h>
#include <KoPointerEvent.h>
#include <kis_cursor.h>
KisToolPath::KisToolPath(KoCanvasBase * canvas)
: KisToolShape(canvas, Qt::ArrowCursor), m_localTool(new LocalTool(canvas, this))
: DelegatedPathTool(canvas, Qt::ArrowCursor,
new __KisToolPathLocalTool(canvas, this))
{
}
KisToolPath::~KisToolPath()
void KisToolPath::requestStrokeEnd()
{
delete m_localTool;
localTool()->endPathWithoutLastPoint();
}
void KisToolPath::activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes)
void KisToolPath::requestStrokeCancellation()
{
KisToolShape::activate(toolActivation, shapes);
m_localTool->activate(toolActivation, shapes);
}
void KisToolPath::deactivate()
{
KisToolShape::deactivate();
m_localTool->deactivate();
localTool()->cancelPath();
}
void KisToolPath::mousePressEvent(KoPointerEvent *event)
{
if(PRESS_CONDITION_OM(event, KisTool::HOVER_MODE,
Qt::LeftButton, Qt::ShiftModifier |
Qt::ControlModifier | Qt::AltModifier)) {
setMode(KisTool::PAINT_MODE);
if (!nodeEditable()) {
return;
}
Q_ASSERT(m_localTool);
m_localTool->mousePressEvent(event);
}
else {
KisToolShape::mousePressEvent(event);
}
}
void KisToolPath::mouseDoubleClickEvent(KoPointerEvent *event)
{
if(PRESS_CONDITION_OM(event, KisTool::HOVER_MODE,
Qt::LeftButton, Qt::ShiftModifier |
Qt::ControlModifier | Qt::AltModifier)) {
Q_ASSERT(m_localTool);
m_localTool->mouseDoubleClickEvent(event);
}
else {
KisToolShape::mouseDoubleClickEvent(event);
}
if (!nodeEditable()) return;
DelegatedPathTool::mousePressEvent(event);
}
void KisToolPath::mouseMoveEvent(KoPointerEvent *event)
{
Q_ASSERT(m_localTool);
m_localTool->mouseMoveEvent(event);
KisToolShape::mouseMoveEvent(event);
}
void KisToolPath::mouseReleaseEvent(KoPointerEvent *event)
{
if(RELEASE_CONDITION(event, KisTool::PAINT_MODE, Qt::LeftButton)) {
setMode(KisTool::HOVER_MODE);
Q_ASSERT(m_localTool);
m_localTool->mouseReleaseEvent(event);
}
else {
KisToolShape::mouseReleaseEvent(event);
}
}
void KisToolPath::paint(QPainter &painter, const KoViewConverter &converter)
{
Q_ASSERT(m_localTool);
m_localTool->paint(painter, converter);
}
QList<QWidget *> KisToolPath::createOptionWidgets()
{
QList<QWidget *> list = KisToolShape::createOptionWidgets();
list.append(m_localTool->createOptionWidgets());
return list;
}
KisToolPath::LocalTool::LocalTool(KoCanvasBase * canvas, KisToolPath* selectingTool)
: KoCreatePathTool(canvas), m_parentTool(selectingTool) {}
__KisToolPathLocalTool::__KisToolPathLocalTool(KoCanvasBase * canvas, KisToolPath* parentTool)
: KoCreatePathTool(canvas), m_parentTool(parentTool) {}
void KisToolPath::LocalTool::paintPath(KoPathShape &pathShape, QPainter &painter, const KoViewConverter &converter)
void __KisToolPathLocalTool::paintPath(KoPathShape &pathShape, QPainter &painter, const KoViewConverter &converter)
{
Q_UNUSED(converter);
......@@ -126,7 +58,7 @@ void KisToolPath::LocalTool::paintPath(KoPathShape &pathShape, QPainter &painter
m_parentTool->paintToolOutline(&painter, m_parentTool->pixelToView(matrix.map(pathShape.outline())));
}
void KisToolPath::LocalTool::addPathShape(KoPathShape* pathShape)
void __KisToolPathLocalTool::addPathShape(KoPathShape* pathShape)
{
m_parentTool->addPathShape(pathShape, i18n("Path"));
}
......
......@@ -24,45 +24,44 @@
#include "flake/kis_node_shape.h"
#include "kis_tool_shape.h"
#include "kis_delegated_tool.h"
#include <KoIcon.h>
class KisSelectionOptions;
class KoCanvasBase;
class KisToolPath;
class KisToolPath : public KisToolShape
{
class __KisToolPathLocalTool : public KoCreatePathTool {
public:
__KisToolPathLocalTool(KoCanvasBase * canvas, KisToolPath* parentTool);
virtual void paintPath(KoPathShape &path, QPainter &painter, const KoViewConverter &converter);
virtual void addPathShape(KoPathShape* pathShape);
using KoCreatePathTool::createOptionWidgets;
using KoCreatePathTool::endPathWithoutLastPoint;
using KoCreatePathTool::endPath;
using KoCreatePathTool::cancelPath;
private:
KisToolPath* const m_parentTool;
};
typedef KisDelegatedTool<KisToolShape, __KisToolPathLocalTool> DelegatedPathTool;
class KisToolPath : public DelegatedPathTool
{
Q_OBJECT
public:
KisToolPath(KoCanvasBase * canvas);
virtual ~KisToolPath();
virtual void paint(QPainter &painter, const KoViewConverter &converter);
void mousePressEvent(KoPointerEvent *event);
void mouseDoubleClickEvent(KoPointerEvent *event);
void mouseMoveEvent(KoPointerEvent *event);
void mouseReleaseEvent(KoPointerEvent *event);
public slots:
virtual void activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes);
virtual void deactivate();
private:
/// reimplemented
virtual QList<QWidget *> createOptionWidgets();
class LocalTool : public KoCreatePathTool {
friend class KisToolPath;
public:
LocalTool(KoCanvasBase * canvas, KisToolPath* selectingTool);
virtual void paintPath(KoPathShape &path, QPainter &painter, const KoViewConverter &converter);
virtual void addPathShape(KoPathShape* pathShape);
private:
KisToolPath* const m_parentTool;
};
LocalTool* const m_localTool;
protected:
void requestStrokeCancellation();
void requestStrokeEnd();
private:
friend class __KisToolPathLocalTool;
};
class KisToolPathFactory : public KoToolFactoryBase
......
......@@ -23,46 +23,51 @@
#include "kis_cursor.h"
#include "kis_image.h"
#include "kis_painter.h"
#include "kis_paintop_registry.h"
#include "kis_selection_options.h"
#include "kis_canvas_resource_provider.h"
#include "kis_canvas2.h"
#include "kis_pixel_selection.h"
#include "kis_selection_tool_helper.h"
#include "kis_shape_tool_helper.h"
KisToolSelectPath::KisToolSelectPath(KoCanvasBase * canvas)
: KisToolSelectBase(canvas,
KisCursor::load("tool_polygonal_selection_cursor.png", 6, 6),
i18n("Path Selection")),
m_localTool(new LocalTool(canvas, this))
: DelegatedSelectPathTool(canvas,
KisCursor::load("tool_polygonal_selection_cursor.png", 6, 6),
new __KisToolSelectPathLocalTool(canvas, this))
{
}
KisToolSelectPath::~KisToolSelectPath()
void KisToolSelectPath::requestStrokeEnd()
{
delete m_localTool;
localTool()->endPathWithoutLastPoint();
}
QList<QWidget *> KisToolSelectPath::createOptionWidgets()
void KisToolSelectPath::requestStrokeCancellation()
{
QList<QWidget*> widgetsList = m_localTool->createOptionWidgets();
localTool()->cancelPath();
}
KisToolSelectBase::createOptionWidget();
selectionOptionWidget()->disableAntiAliasSelectionOption();
widgetsList.append(selectionOptionWidget());
void KisToolSelectPath::mousePressEvent(KoPointerEvent* event)
{
if (!selectionEditable()) return;
DelegatedSelectPathTool::mousePressEvent(event);
}
QList<QWidget *> KisToolSelectPath::createOptionWidgets()
{
QList<QWidget*> widgetsList =
DelegatedSelectPathTool::createOptionWidgets();
selectionOptionWidget()->disableAntiAliasSelectionOption();
return widgetsList;
}
KisToolSelectPath::LocalTool::LocalTool(KoCanvasBase * canvas, KisToolSelectPath* selectingTool)
: KoCreatePathTool(canvas), m_selectionTool(selectingTool)
__KisToolSelectPathLocalTool::__KisToolSelectPathLocalTool(KoCanvasBase * canvas, KisToolSelectPath* parentTool)
: KoCreatePathTool(canvas), m_selectionTool(parentTool)
{
}
void KisToolSelectPath::LocalTool::paintPath(KoPathShape &pathShape, QPainter &painter, const KoViewConverter &converter)
void __KisToolSelectPathLocalTool::paintPath(KoPathShape &pathShape, QPainter &painter, const KoViewConverter &converter)
{
Q_UNUSED(converter);
KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas());
......@@ -75,7 +80,7 @@ void KisToolSelectPath::LocalTool::paintPath(KoPathShape &pathShape, QPainter &p
m_selectionTool->paintToolOutline(&painter, m_selectionTool->pixelToView(matrix.map(pathShape.outline())));
}
void KisToolSelectPath::LocalTool::addPathShape(KoPathShape* pathShape)
void __KisToolSelectPathLocalTool::addPathShape(KoPathShape* pathShape)
{
KisNodeSP currentNode =
canvas()->resourceManager()->resource(KisCanvasResourceProvider::CurrentKritaNode).value<KisNodeSP>();
......@@ -117,15 +122,4 @@ void KisToolSelectPath::LocalTool::addPathShape(KoPathShape* pathShape)
}
}
void KisToolSelectPath::mousePressEvent(KoPointerEvent* event)
{
if (!selectionEditable()) {
return;
}
m_localTool->mousePressEvent(event);
KisTool::mousePressEvent(event);
}
#include "kis_tool_select_path.moc"
......@@ -22,65 +22,55 @@
#include <KoCreatePathTool.h>
#include <KoToolFactoryBase.h>
#include "kis_tool_select_base.h"
#include "kis_delegated_tool.h"
#include <KoPointerEvent.h>
#include <KoIcon.h>
class KoCanvasBase;
class KoShapeStroke;
class KisToolSelectPath;
#define REDIRECT_EVENT_0P(name) \
void name() { \
m_localTool->name(); \
KisToolSelectBase::name(); \
}
#define REDIRECT_EVENT_1P(name, P1) \
void name(P1 p1) { \
m_localTool->name(p1); \
KisToolSelectBase::name(p1); \
}
class __KisToolSelectPathLocalTool : public KoCreatePathTool {
public:
__KisToolSelectPathLocalTool(KoCanvasBase * canvas, KisToolSelectPath* parentTool);
virtual void paintPath(KoPathShape &path, QPainter &painter, const KoViewConverter &converter);
virtual void addPathShape(KoPathShape* pathShape);
using KoCreatePathTool::createOptionWidgets;
using KoCreatePathTool::endPathWithoutLastPoint;
using KoCreatePathTool::endPath;
using KoCreatePathTool::cancelPath;
private:
KisToolSelectPath* const m_selectionTool;
KoShapeStroke* m_borderBackup;
};
#define REDIRECT_EVENT_2P(name, P1, P2) \
void name(P1 p1, P2 p2) { \
m_localTool->name(p1, p2); \
KisToolSelectBase::name(p1, p2); \
struct __KisToolSelectBaseWrapper : public KisToolSelectBase {
__KisToolSelectBaseWrapper(KoCanvasBase *canvas,
const QCursor &cursor)
: KisToolSelectBase(canvas, cursor, i18n("Path Selection"))
{
}
};
typedef KisDelegatedTool<__KisToolSelectBaseWrapper, __KisToolSelectPathLocalTool> DelegatedSelectPathTool;
class KisToolSelectPath : public KisToolSelectBase
class KisToolSelectPath : public DelegatedSelectPathTool
{
Q_OBJECT
public:
KisToolSelectPath(KoCanvasBase * canvas);
virtual ~KisToolSelectPath();
void paint(QPainter& gc, const KoViewConverter &converter) {m_localTool->paint(gc, converter);}
void mousePressEvent(KoPointerEvent* event);
REDIRECT_EVENT_1P(mouseMoveEvent, KoPointerEvent*);
REDIRECT_EVENT_1P(mouseReleaseEvent, KoPointerEvent*);
REDIRECT_EVENT_1P(keyPressEvent, QKeyEvent*);
REDIRECT_EVENT_1P(keyReleaseEvent, QKeyEvent*);
REDIRECT_EVENT_2P(activate, ToolActivation, const QSet<KoShape*>&);
REDIRECT_EVENT_0P(deactivate);
private:
/// reimplemented
virtual QList<QWidget *> createOptionWidgets();
class LocalTool : public KoCreatePathTool {
friend class KisToolSelectPath;
public:
LocalTool(KoCanvasBase * canvas, KisToolSelectPath* selectingTool);
virtual void paintPath(KoPathShape &path, QPainter &painter, const KoViewConverter &converter);
virtual void addPathShape(KoPathShape* pathShape);
private:
KisToolSelectPath* const m_selectionTool;
KoShapeStroke* m_borderBackup;
};
LocalTool* const m_localTool;
protected:
void requestStrokeCancellation();
void requestStrokeEnd();
friend class __KisToolSelectPathLocalTool;
QList<QWidget *> createOptionWidgets();
};
class KisToolSelectPathFactory : public KoToolFactoryBase
......
/*
* Copyright (c) 2013 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __KIS_DELEGATED_TOOL_H
#define __KIS_DELEGATED_TOOL_H
#include <KoPointerEvent.h>
template <class BaseClass, class DelegateTool>
class KisDelegatedTool : public BaseClass
{
public:
KisDelegatedTool(KoCanvasBase *canvas,
const QCursor &cursor,
DelegateTool *delegateTool)
: BaseClass(canvas, cursor),
m_localTool(delegateTool)
{
}
DelegateTool* localTool() const {
return m_localTool.data();
}
void activate(typename BaseClass::ToolActivation toolActivation, const QSet<KoShape*> &shapes)
{
BaseClass::activate(toolActivation, shapes);
m_localTool->activate(toolActivation, shapes);
}
void deactivate()
{
m_localTool->deactivate();
BaseClass::deactivate();
}
void mousePressEvent(KoPointerEvent *event)
{
if(PRESS_CONDITION_OM(event, KisTool::HOVER_MODE,
Qt::LeftButton, Qt::ShiftModifier |
Qt::ControlModifier | Qt::AltModifier)) {
this->setMode(KisTool::PAINT_MODE);
Q_ASSERT(m_localTool);
m_localTool->mousePressEvent(event);
}
else {
BaseClass::mousePressEvent(event);
}
}
void mouseDoubleClickEvent(KoPointerEvent *event)
{
if(PRESS_CONDITION_OM(event, KisTool::HOVER_MODE,
Qt::LeftButton, Qt::ShiftModifier |
Qt::ControlModifier | Qt::AltModifier)) {
Q_ASSERT(m_localTool);
m_localTool->mouseDoubleClickEvent(event);
}
else {
BaseClass::mouseDoubleClickEvent(event);
}
}
void mouseMoveEvent(KoPointerEvent *event)
{
Q_ASSERT(m_localTool);
m_localTool->mouseMoveEvent(event);
BaseClass::mouseMoveEvent(event);
}
void mouseReleaseEvent(KoPointerEvent *event)
{
if(RELEASE_CONDITION(event, KisTool::PAINT_MODE, Qt::LeftButton)) {
this->setMode(KisTool::HOVER_MODE);
Q_ASSERT(m_localTool);
m_localTool->mouseReleaseEvent(event);
}
else {
BaseClass::mouseReleaseEvent(event);
}
}
void paint(QPainter &painter, const KoViewConverter &converter)
{
Q_ASSERT(m_localTool);
m_localTool->paint(painter, converter);
}
QList<QWidget *> createOptionWidgets()
{
QList<QWidget *> list = BaseClass::createOptionWidgets();
list.append(m_localTool->createOptionWidgets());
return list;
}
private:
QScopedPointer<DelegateTool> m_localTool;
};
#endif /* __KIS_DELEGATED_TOOL_H */
......@@ -29,26 +29,26 @@
#include <kis_types.h>
#define PRESS_CONDITION(_event, _mode, _button, _modifier) \
(mode() == (_mode) && (_event)->button() == (_button) && \
(_event)->modifiers() == (_modifier) && !specialModifierActive())
(this->mode() == (_mode) && (_event)->button() == (_button) && \
(_event)->modifiers() == (_modifier) && !this->specialModifierActive())
#define PRESS_CONDITION_WB(_event, _mode, _button, _modifier) \
(mode() == (_mode) && (_event)->button() & (_button) && \
(_event)->modifiers() == (_modifier) && !specialModifierActive())
(this->mode() == (_mode) && (_event)->button() & (_button) && \
(_event)->modifiers() == (_modifier) && !this->specialModifierActive())
#define PRESS_CONDITION_OM(_event, _mode, _button, _modifier) \
(mode() == (_mode) && (_event)->button() == (_button) && \
(this->mode() == (_mode) && (_event)->button() == (_button) && \
((_event)->modifiers() & (_modifier) || \
(_event)->modifiers() == Qt::NoModifier) && \
!specialModifierActive())
!this->specialModifierActive())
#define RELEASE_CONDITION(_event, _mode, _button) \
(mode() == (_mode) && (_event)->button() == (_button))
(this->mode() == (_mode) && (_event)->button() == (_button))
#define RELEASE_CONDITION_WB(_event, _mode, _button) \
(mode() == (_mode) && (_event)->button() & (_button))
(this->mode() == (_mode) && (_event)->button() & (_button))
#define MOVE_CONDITION(_event, _mode) (mode() == (_mode))
#define MOVE_CONDITION(_event, _mode) (this->mode() == (_mode))
class KActionCollection;
class KoCanvasBase;
......
......@@ -127,14 +127,7 @@ void KoCreatePathTool::mousePressEvent(KoPointerEvent *event)
Q_D(KoCreatePathTool);
if (event->button() == Qt::RightButton || (event->button() == Qt::LeftButton && event->modifiers() & Qt::ShiftModifier)) {
if (d->shape) {
// repaint the shape before removing the last point
canvas()->updateCanvas(d->shape->boundingRect());
delete d->shape->removePoint(d->shape->pathPointIndex(d->activePoint));
d->addPathShape();
}
// Return as otherwise a point would be added
endPathWithoutLastPoint();
return;
}
......@@ -146,7 +139,7 @@ void KoCreatePathTool::mousePressEvent(KoPointerEvent *event)
// we are closing the path, so reset the existing start path point
d->existingStartPoint = 0;
// finish path
d->addPathShape();
endPath();
} else {
canvas()->updateCanvas(canvas()->snapGuide()->boundingRect());
......@@ -158,7 +151,7 @@ void KoCreatePathTool::mousePressEvent(KoPointerEvent *event)
point = d->existingEndPoint.path->shapeToDocument(d->existingEndPoint.point->point());
d->activePoint->setPoint(point);
// finish path
d->addPathShape();
endPath();
} else {
d->activePoint->setPoint(point);
canvas()->updateCanvas(d->shape->boundingRect());
......@@ -204,12 +197,7 @@ void KoCreatePathTool::mouseDoubleClickEvent(KoPointerEvent *event)
//remove handle
canvas()->updateCanvas(handlePaintRect(event->point));
if (d->shape) {
// the first click of the double click created a new point which has the be removed again
d->shape->removePoint(d->shape->pathPointIndex(d->activePoint));
d->addPathShape();
}
endPathWithoutLastPoint();
}
void KoCreatePathTool::mouseMoveEvent(KoPointerEvent *event)
......@@ -293,20 +281,27 @@ void KoCreatePathTool::keyPressEvent(QKeyEvent *event)
event->ignore();
}
void KoCreatePathTool::activate(ToolActivation, const QSet<KoShape*> &)
void KoCreatePathTool::endPath()
{
Q_D(KoCreatePathTool);
useCursor(Qt::ArrowCursor);
// retrieve the actual global handle radius
d->handleRadius = handleRadius();
d->addPathShape();