...
 
Commits (6)
......@@ -22,24 +22,92 @@
#include "KisDocument.h"
#include <kis_image.h>
#include <QList>
#include <QListIterator>
struct KisChangeGuidesCommand::Private
{
Private(KisDocument *_doc) : doc(_doc) {}
Private(KisDocument *_doc, KisChangeGuidesCommand *q) : doc(_doc), q(q) {}
bool sameOrOnlyMovedOneGuideBetween(const KisGuidesConfig &first, const KisGuidesConfig &second);
enum Status {
NO_DIFF = 0,
ONE_DIFF = 1,
ADDITION = 4,
REMOVAL = 16,
OTHER_DIFF = 1024
};
Status diff(const QList<qreal> &first, const QList<qreal> &second);
KisDocument *doc;
KisChangeGuidesCommand *q;
KisGuidesConfig oldGuides;
KisGuidesConfig newGuides;
};
bool KisChangeGuidesCommand::Private::sameOrOnlyMovedOneGuideBetween(const KisGuidesConfig &first, const KisGuidesConfig &second)
{
int ret = diff(first.horizontalGuideLines(), second.horizontalGuideLines()) +
diff(first.verticalGuideLines(), second.verticalGuideLines());
if (ret == ADDITION) {
q->setText(kundo2_i18n("Add Guide"));
} else if (ret == REMOVAL) {
q->setText(kundo2_i18n("Remove Guide"));
} else if (ret == NO_DIFF || ret == ONE_DIFF) { // meaning we will still merge it
// XXX: how to deal with NO_DIFF (the command "should" be removed -- how?)
q->setText(kundo2_i18n("Edit Guides"));
} else {
return false;
}
return true;
}
KisChangeGuidesCommand::Private::Status KisChangeGuidesCommand::Private::diff(const QList<qreal> &first, const QList<qreal> &second)
{
if (first.size() == second.size()) {
int diffCount = 0;
for (int i = 0; i < first.size(); ++i) {
if (first[i] != second[i]) {
++diffCount;
if (diffCount > 1) {
return OTHER_DIFF;
}
}
}
return diffCount == 0 ? NO_DIFF : ONE_DIFF;
} else if (first.size() - second.size() == -1) { // added a guide
QList<qreal> beforeRemoval = second;
beforeRemoval.takeLast();
return first == beforeRemoval ? ADDITION : OTHER_DIFF;
} else if (first.size() - second.size() == 1) { // removed a guide
bool skippedItem = false;
for (QListIterator<qreal> i(first), j(second); i.hasNext() && j.hasNext(); ) {
qreal curFirst = i.next();
qreal curSecond = j.next();
if (!skippedItem && curFirst != curSecond) {
curFirst = i.next(); // try to go to the next item and see if it matches
}
if (curFirst != curSecond) {
return OTHER_DIFF;
}
}
// here we conclude only one guide is removed
return REMOVAL;
} else {
return OTHER_DIFF;
}
}
KisChangeGuidesCommand::KisChangeGuidesCommand(KisDocument *doc, const KisGuidesConfig &newGuides)
: KUndo2Command(kundo2_i18n("Edit Guides")),
m_d(new Private(doc))
m_d(new Private(doc, this))
{
m_d->oldGuides = doc->guidesConfig();
m_d->newGuides = newGuides;
// update the undo command text
m_d->sameOrOnlyMovedOneGuideBetween(m_d->oldGuides, m_d->newGuides);
}
KisChangeGuidesCommand::~KisChangeGuidesCommand()
......@@ -69,8 +137,15 @@ bool KisChangeGuidesCommand::mergeWith(const KUndo2Command *command)
dynamic_cast<const KisChangeGuidesCommand*>(command);
if (rhs) {
m_d->newGuides = rhs->m_d->newGuides;
result = true;
// we want to only merge consecutive movements, or creation then movement, or movement then deletion
// there should not be any changes not on the stack (see kis_guides_manager.cpp)
// nor any addition/removal of guides
// nor the movement of other guides
if (m_d->newGuides == rhs->m_d->oldGuides &&
m_d->sameOrOnlyMovedOneGuideBetween(m_d->oldGuides, rhs->m_d->newGuides)) {
m_d->newGuides = rhs->m_d->newGuides;
result = true;
}
}
return result;
......
......@@ -97,6 +97,12 @@ bool KisGuidesConfig::operator==(const KisGuidesConfig &rhs) const
return *d == *rhs.d;
}
bool KisGuidesConfig::hasSamePositionAs(const KisGuidesConfig &rhs) const
{
return horizontalGuideLines() == rhs.horizontalGuideLines() &&
verticalGuideLines() == rhs.verticalGuideLines();
}
void KisGuidesConfig::setHorizontalGuideLines(const QList<qreal> &lines)
{
d->horzGuideLines = lines;
......
......@@ -50,6 +50,7 @@ public:
KisGuidesConfig(const KisGuidesConfig &rhs);
KisGuidesConfig& operator=(const KisGuidesConfig &rhs);
bool operator==(const KisGuidesConfig &rhs) const;
bool hasSamePositionAs(const KisGuidesConfig &rhs) const;
/**
* @brief Set the positions of the horizontal guide lines
......
......@@ -83,6 +83,7 @@ struct KisGuidesManager::Private
Qt::MouseButton getButtonFromEvent(QEvent *event);
QAction* createShortenedAction(const QString &text, const QString &parentId, QObject *parent);
void syncAction(const QString &actionName, bool value);
bool needsUndoCommand();
GuideHandle currentGuide;
......@@ -131,8 +132,10 @@ void KisGuidesManager::slotUploadConfigToDocument()
KisSignalsBlocker b(doc);
if (m_d->shouldSetModified) {
KUndo2Command *cmd = new KisChangeGuidesCommand(doc, value);
doc->addCommand(cmd);
if (m_d->needsUndoCommand()) {
KUndo2Command *cmd = new KisChangeGuidesCommand(doc, value);
doc->addCommand(cmd);
}
} else {
doc->setGuidesConfig(value);
}
......@@ -196,6 +199,17 @@ void KisGuidesManager::Private::syncAction(const QString &actionName, bool value
action->setChecked(value);
}
bool KisGuidesManager::Private::needsUndoCommand()
{
const KisGuidesConfig &value = guidesConfig;
KisDocument *doc = view ? view->document() : 0;
if (!doc) {
return false;
}
return !(doc->guidesConfig().hasSamePositionAs(value));
}
void KisGuidesManager::syncActionsStatus()
{
if (!m_d->view) return;
......
This diff is collapsed.
......@@ -27,9 +27,11 @@
#include <QObject>
#include <QColor>
#include <QXmlStreamWriter>
#include <QMap>
#include <kritaui_export.h>
#include <kis_shared.h>
#include <kis_types.h>
class QPainter;
class QRect;
......@@ -74,12 +76,12 @@ public:
void uncache();
KisPaintingAssistantHandle& operator=(const QPointF&);
void setType(char type);
char handleType();
char handleType() const;
private:
void registerAssistant(KisPaintingAssistant*);
void unregisterAssistant(KisPaintingAssistant*);
bool containsAssistant(KisPaintingAssistant*);
bool containsAssistant(KisPaintingAssistant*) const;
private:
struct Private;
......@@ -95,6 +97,7 @@ class KRITAUI_EXPORT KisPaintingAssistant
public:
KisPaintingAssistant(const QString& id, const QString& name);
virtual ~KisPaintingAssistant();
virtual KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const = 0;
const QString& id() const;
const QString& name() const;
bool isSnappingActive() const;
......@@ -189,6 +192,8 @@ public:
static double norm2(const QPointF& p);
protected:
explicit KisPaintingAssistant(const KisPaintingAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
virtual QRect boundingRect() const;
/// performance layer where the graphics can be drawn from a cache instead of generated every render update
......
......@@ -12,6 +12,7 @@ set(kritaassistanttool_SOURCES
RulerAssistant.cc
SplineAssistant.cc
VanishingPointAssistant.cc
EditAssistantsCommand.cpp
)
ki18n_wrap_ui(kritaassistanttool_SOURCES AssistantsToolOptions.ui )
......
......@@ -35,6 +35,18 @@ ConcentricEllipseAssistant::ConcentricEllipseAssistant()
{
}
KisPaintingAssistantSP ConcentricEllipseAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new ConcentricEllipseAssistant(*this, handleMap));
}
ConcentricEllipseAssistant::ConcentricEllipseAssistant(const ConcentricEllipseAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisPaintingAssistant(rhs, handleMap)
, m_ellipse(rhs.m_ellipse)
, m_extraEllipse(rhs.m_extraEllipse)
{
}
QPointF ConcentricEllipseAssistant::project(const QPointF& pt, const QPointF& strokeBegin) const
{
Q_ASSERT(isAssistantComplete());
......
......@@ -29,6 +29,7 @@ class ConcentricEllipseAssistant : public KisPaintingAssistant
{
public:
ConcentricEllipseAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
QPointF buttonPosition() const override;
int numHandles() const override { return 3; }
......@@ -42,6 +43,7 @@ private:
QPointF project(const QPointF& pt, const QPointF& strokeBegin) const;
mutable Ellipse m_ellipse;
mutable Ellipse m_extraEllipse;
explicit ConcentricEllipseAssistant(const ConcentricEllipseAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
};
class ConcentricEllipseAssistantFactory : public KisPaintingAssistantFactory
......
/*
* Copyright (c) 2019 Tusooa Zhu <tusooa@vista.aero>
*
* 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.
*/
#include "EditAssistantsCommand.h"
#include <QListIterator>
#include <kis_canvas2.h>
#include <KisView.h>
#include <KisDocument.h>
#include <KisViewManager.h>
#include <kis_canvas_resource_provider.h>
#include <kis_painting_assistants_decoration.h>
EditAssistantsCommand::EditAssistantsCommand(QPointer<KisCanvas2> canvas, AssistantSPList origAssistants, AssistantSPList newAssistants, KUndo2Command *parent)
: KUndo2Command(kundo2_i18n("Edit Assistants"), parent)
, m_canvas(canvas)
, m_origAssistants(origAssistants)
, m_newAssistants(newAssistants)
, m_index(-1)
, m_firstRedo(true)
, m_type(EDIT)
{
}
EditAssistantsCommand::EditAssistantsCommand(QPointer<KisCanvas2> canvas, AssistantSPList origAssistants, AssistantSPList newAssistants, Type type, int index, KUndo2Command *parent)
: KUndo2Command((type == ADD ? kundo2_i18n("Add Assistant") : kundo2_i18n("Remove Assistant")), parent)
, m_canvas(canvas)
, m_origAssistants(origAssistants)
, m_newAssistants(newAssistants)
, m_index(index)
, m_firstRedo(true)
, m_type(type)
{
KIS_ASSERT_RECOVER_RETURN(type != EDIT);
}
void EditAssistantsCommand::replaceWith(AssistantSPList assistants, Type type)
{
AssistantSPList curAssistants = m_canvas->paintingAssistantsDecoration()->assistants();
if (type == EDIT) {
KIS_ASSERT_RECOVER_RETURN(curAssistants.size() == assistants.size());
} else if (type == ADD) {
KIS_ASSERT_RECOVER_RETURN(curAssistants.size() == assistants.size() - 1);
} else { // type == REMOVE
KIS_ASSERT_RECOVER_RETURN(curAssistants.size() == assistants.size() + 1);
}
Q_FOREACH (KisPaintingAssistantSP assistant, curAssistants) {
KisAbstractPerspectiveGrid* grid = dynamic_cast<KisAbstractPerspectiveGrid*>(assistant.data());
if (grid) {
m_canvas->viewManager()->canvasResourceProvider()->removePerspectiveGrid(grid);
}
}
m_canvas->imageView()->document()->setAssistants(assistants);
Q_FOREACH (KisPaintingAssistantSP assistant, assistants) {
assistant->uncache();
KisAbstractPerspectiveGrid* grid = dynamic_cast<KisAbstractPerspectiveGrid*>(assistant.data());
if (grid) {
m_canvas->viewManager()->canvasResourceProvider()->addPerspectiveGrid(grid);
}
}
m_canvas->updateCanvas();
}
void EditAssistantsCommand::undo()
{
replaceWith(m_origAssistants, Type(-m_type));
}
void EditAssistantsCommand::redo()
{
// this is a post-execution command
if (m_firstRedo) {
m_firstRedo = false;
return;
}
replaceWith(m_newAssistants, m_type);
}
/*
* Copyright (c) 2019 Tusooa Zhu <tusooa@vista.aero>
*
* 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.
*/
#include <QPointer>
#include <kundo2command.h>
#include <kis_painting_assistant.h>
class KisCanvas2;
class EditAssistantsCommand : public KUndo2Command
{
using AssistantSPList = QList<KisPaintingAssistantSP>;
public:
enum Type {
ADD = -1,
REMOVE = 1,
EDIT = 0
};
EditAssistantsCommand(QPointer<KisCanvas2> canvas, AssistantSPList origAssistants, AssistantSPList newAssistants, KUndo2Command *parent = 0);
EditAssistantsCommand(QPointer<KisCanvas2> canvas, AssistantSPList origAssistants, AssistantSPList newAssistants, Type type, int index, KUndo2Command *parent = 0);
void undo() override;
void redo() override;
private:
void replaceWith(AssistantSPList assistants, Type type = EDIT);
QPointer<KisCanvas2> m_canvas;
AssistantSPList m_origAssistants, m_newAssistants;
int m_index;
bool m_firstRedo;
Type m_type;
};
......@@ -35,6 +35,17 @@ EllipseAssistant::EllipseAssistant()
{
}
EllipseAssistant::EllipseAssistant(const EllipseAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisPaintingAssistant(rhs, handleMap)
, e(rhs.e)
{
}
KisPaintingAssistantSP EllipseAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new EllipseAssistant(*this, handleMap));
}
QPointF EllipseAssistant::project(const QPointF& pt) const
{
Q_ASSERT(isAssistantComplete());
......
......@@ -28,6 +28,7 @@ class EllipseAssistant : public KisPaintingAssistant
{
public:
EllipseAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
QPointF buttonPosition() const override;
int numHandles() const override { return 3; }
......@@ -39,6 +40,7 @@ protected:
void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override;
private:
QPointF project(const QPointF& pt) const;
explicit EllipseAssistant(const EllipseAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
mutable Ellipse e;
};
......
......@@ -39,6 +39,18 @@ FisheyePointAssistant::FisheyePointAssistant()
{
}
FisheyePointAssistant::FisheyePointAssistant(const FisheyePointAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisPaintingAssistant(rhs, handleMap)
, e(rhs.e)
, extraE(rhs.extraE)
{
}
KisPaintingAssistantSP FisheyePointAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new FisheyePointAssistant(*this, handleMap));
}
QPointF FisheyePointAssistant::project(const QPointF& pt, const QPointF& strokeBegin)
{
const static QPointF nullPoint(std::numeric_limits<qreal>::quiet_NaN(), std::numeric_limits<qreal>::quiet_NaN());
......
......@@ -33,6 +33,7 @@ class FisheyePointAssistant : public KisPaintingAssistant
{
public:
FisheyePointAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
//virtual void endStroke();
QPointF buttonPosition() const override;
......@@ -46,6 +47,7 @@ protected:
void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override;
private:
QPointF project(const QPointF& pt, const QPointF& strokeBegin);
explicit FisheyePointAssistant(const FisheyePointAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
mutable Ellipse e;
mutable Ellipse extraE;
};
......
......@@ -38,6 +38,16 @@ InfiniteRulerAssistant::InfiniteRulerAssistant()
{
}
InfiniteRulerAssistant::InfiniteRulerAssistant(const InfiniteRulerAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisPaintingAssistant(rhs, handleMap)
{
}
KisPaintingAssistantSP InfiniteRulerAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new InfiniteRulerAssistant(*this, handleMap));
}
QPointF InfiniteRulerAssistant::project(const QPointF& pt, const QPointF& strokeBegin)
{
Q_ASSERT(isAssistantComplete());
......
......@@ -34,6 +34,7 @@ class InfiniteRulerAssistant : public KisPaintingAssistant
{
public:
InfiniteRulerAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
//virtual void endStroke();
QPointF buttonPosition() const override;
......@@ -45,6 +46,7 @@ protected:
void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override;
private:
QPointF project(const QPointF& pt, const QPointF& strokeBegin);
explicit InfiniteRulerAssistant(const InfiniteRulerAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
};
class InfiniteRulerAssistantFactory : public KisPaintingAssistantFactory
......
......@@ -38,6 +38,16 @@ ParallelRulerAssistant::ParallelRulerAssistant()
{
}
KisPaintingAssistantSP ParallelRulerAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new ParallelRulerAssistant(*this, handleMap));
}
ParallelRulerAssistant::ParallelRulerAssistant(const ParallelRulerAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisPaintingAssistant(rhs, handleMap)
{
}
QPointF ParallelRulerAssistant::project(const QPointF& pt, const QPointF& strokeBegin)
{
Q_ASSERT(isAssistantComplete());
......
......@@ -34,6 +34,7 @@ class ParallelRulerAssistant : public KisPaintingAssistant
{
public:
ParallelRulerAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
//virtual void endStroke();
QPointF buttonPosition() const override;
......@@ -45,6 +46,7 @@ protected:
void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override;
private:
QPointF project(const QPointF& pt, const QPointF& strokeBegin);
explicit ParallelRulerAssistant(const ParallelRulerAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
};
class ParallelRulerAssistantFactory : public KisPaintingAssistantFactory
......
......@@ -39,6 +39,23 @@ PerspectiveAssistant::PerspectiveAssistant(QObject *parent)
{
}
PerspectiveAssistant::PerspectiveAssistant(const PerspectiveAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisAbstractPerspectiveGrid(rhs.parent())
, KisPaintingAssistant(rhs, handleMap)
, m_snapLine(rhs.m_snapLine)
, m_cachedTransform(rhs.m_cachedTransform)
, m_cachedPolygon(rhs.m_cachedPolygon)
, m_cacheValid(rhs.m_cacheValid)
{
for (int i = 0; i < 4; ++i) {
m_cachedPoints[i] = rhs.m_cachedPoints[i];
}
}
KisPaintingAssistantSP PerspectiveAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new PerspectiveAssistant(*this, handleMap));
}
// squared distance from a point to a line
inline qreal distsqr(const QPointF& pt, const QLineF& line)
{
......
......@@ -32,6 +32,7 @@ class PerspectiveAssistant : public KisAbstractPerspectiveGrid, public KisPainti
Q_OBJECT
public:
PerspectiveAssistant(QObject * parent = 0);
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
void endStroke() override;
QPointF buttonPosition() const override;
......@@ -52,6 +53,7 @@ private:
bool quad(QPolygonF& out) const;
// finds the transform from perspective coordinates (a unit square) to the document
bool getTransform(QPolygonF& polyOut, QTransform& transformOut) const;
explicit PerspectiveAssistant(const PerspectiveAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
// which direction to snap to (in transformed coordinates)
QLineF m_snapLine;
......
......@@ -35,6 +35,16 @@ RulerAssistant::RulerAssistant()
{
}
KisPaintingAssistantSP RulerAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new RulerAssistant(*this, handleMap));
}
RulerAssistant::RulerAssistant(const RulerAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisPaintingAssistant(rhs, handleMap)
{
}
QPointF RulerAssistant::project(const QPointF& pt) const
{
Q_ASSERT(isAssistantComplete());
......
......@@ -19,6 +19,8 @@
#ifndef _RULER_ASSISTANT_H_
#define _RULER_ASSISTANT_H_
#include <QMap>
#include "kis_painting_assistant.h"
class Ruler;
......@@ -27,6 +29,7 @@ class RulerAssistant : public KisPaintingAssistant
{
public:
RulerAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
QPointF buttonPosition() const override;
int numHandles() const override { return 2; }
......@@ -37,6 +40,7 @@ protected:
void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override;
private:
QPointF project(const QPointF& pt) const;
explicit RulerAssistant(const RulerAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
};
class RulerAssistantFactory : public KisPaintingAssistantFactory
......
......@@ -38,6 +38,17 @@ SplineAssistant::SplineAssistant()
{
}
SplineAssistant::SplineAssistant(const SplineAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisPaintingAssistant(rhs, handleMap)
, m_canvas(rhs.m_canvas)
{
}
KisPaintingAssistantSP SplineAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new SplineAssistant(*this, handleMap));
}
// parametric form of a cubic spline (B(t) = (1-t)^3 P0 + 3 (1-t)^2 t P1 + 3 (1-t) t^2 P2 + t^3 P3)
inline QPointF B(qreal t, const QPointF& P0, const QPointF& P1, const QPointF& P2, const QPointF& P3)
{
......
......@@ -27,6 +27,7 @@ class SplineAssistant : public KisPaintingAssistant
{
public:
SplineAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
QPointF buttonPosition() const override;
int numHandles() const override { return 4; }
......@@ -37,6 +38,7 @@ protected:
void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override;
private:
QPointF project(const QPointF& pt) const;
explicit SplineAssistant(const SplineAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
/// used for getting the decoration so the bezier handles aren't drawn while editing
KisCanvas2* m_canvas;
......
......@@ -38,6 +38,18 @@ VanishingPointAssistant::VanishingPointAssistant()
{
}
VanishingPointAssistant::VanishingPointAssistant(const VanishingPointAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap)
: KisPaintingAssistant(rhs, handleMap)
, m_canvas(rhs.m_canvas)
, m_referenceLineDensity(rhs.m_referenceLineDensity)
{
}
KisPaintingAssistantSP VanishingPointAssistant::clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const
{
return KisPaintingAssistantSP(new VanishingPointAssistant(*this, handleMap));
}
QPointF VanishingPointAssistant::project(const QPointF& pt, const QPointF& strokeBegin)
{
//Q_ASSERT(handles().size() == 1 || handles().size() == 5);
......
......@@ -45,6 +45,7 @@ class VanishingPointAssistant : public KisPaintingAssistant
{
public:
VanishingPointAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
//virtual void endStroke();
QPointF buttonPosition() const override;
......@@ -63,6 +64,7 @@ protected:
void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override;
private:
QPointF project(const QPointF& pt, const QPointF& strokeBegin);
explicit VanishingPointAssistant(const VanishingPointAssistant &rhs, QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap);
KisCanvas2 *m_canvas;
float m_referenceLineDensity = 15.0;
......
......@@ -48,6 +48,8 @@
#include <kis_painting_assistants_decoration.h>
#include "kis_global.h"
#include "VanishingPointAssistant.h"
#include "EditAssistantsCommand.h"
#include <kis_undo_adapter.h>
#include <math.h>
......@@ -98,6 +100,8 @@ void KisAssistantTool::deactivate()
void KisAssistantTool::beginPrimaryAction(KoPointerEvent *event)
{
setMode(KisTool::PAINT_MODE);
m_origAssistantList = cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants());
bool newAssistantAllowed = true;
KisPaintingAssistantsDecorationSP canvasDecoration = m_canvas->paintingAssistantsDecoration();
......@@ -508,16 +512,21 @@ void KisAssistantTool::endPrimaryAction(KoPointerEvent *event)
{
setMode(KisTool::HOVER_MODE);
if (m_handleDrag) {
if (!(event->modifiers() & Qt::ShiftModifier) && m_handleCombine) {
m_handleCombine->mergeWith(m_handleDrag);
m_handleCombine->uncache();
m_handles = m_canvas->paintingAssistantsDecoration()->handles();
if (m_handleDrag || m_assistantDrag) {
if (m_handleDrag) {
if (!(event->modifiers() & Qt::ShiftModifier) && m_handleCombine) {
m_handleCombine->mergeWith(m_handleDrag);
m_handleCombine->uncache();
m_handles = m_canvas->paintingAssistantsDecoration()->handles();
}
m_handleDrag = m_handleCombine = 0;
} else {
m_assistantDrag.clear();
}
m_handleDrag = m_handleCombine = 0;
} else if (m_assistantDrag) {
m_assistantDrag.clear();
dbgUI << "creating undo command...";
KUndo2Command *command = new EditAssistantsCommand(m_canvas, m_origAssistantList, cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()));
m_canvas->viewManager()->undoAdapter()->addCommand(command);
dbgUI << "done";
} else if(m_internalMode == MODE_DRAGGING_TRANSLATING_TWONODES) {
addAssistant();
m_internalMode = MODE_CREATION;
......@@ -529,29 +538,52 @@ void KisAssistantTool::endPrimaryAction(KoPointerEvent *event)
m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas
}
QList<KisPaintingAssistantSP> KisAssistantTool::cloneAssistantList(const QList<KisPaintingAssistantSP> &list) const
{
QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> handleMap;
QList<KisPaintingAssistantSP> clonedList;
dbgUI << "cloning assistants...";
for (auto i = list.begin(); i != list.end(); ++i) {
clonedList << (*i)->clone(handleMap);
}
dbgUI << "done";
return clonedList;
}
void KisAssistantTool::addAssistant()
{
m_canvas->paintingAssistantsDecoration()->addAssistant(m_newAssistant);
m_handles = m_canvas->paintingAssistantsDecoration()->handles();
m_canvas->paintingAssistantsDecoration()->setSelectedAssistant(m_newAssistant);
updateToolOptionsUI(); // vanishing point assistant will get an extra option
KisAbstractPerspectiveGrid* grid = dynamic_cast<KisAbstractPerspectiveGrid*>(m_newAssistant.data());
if (grid) {
m_canvas->viewManager()->canvasResourceProvider()->addPerspectiveGrid(grid);
}
QList<KisPaintingAssistantSP> assistants = m_canvas->paintingAssistantsDecoration()->assistants();
KUndo2Command *addAssistantCmd = new EditAssistantsCommand(m_canvas, m_origAssistantList, cloneAssistantList(assistants), EditAssistantsCommand::ADD, assistants.indexOf(m_newAssistant));
m_canvas->viewManager()->undoAdapter()->addCommand(addAssistantCmd);
m_handles = m_canvas->paintingAssistantsDecoration()->handles();
m_canvas->paintingAssistantsDecoration()->setSelectedAssistant(m_newAssistant);
updateToolOptionsUI(); // vanishing point assistant will get an extra option
m_newAssistant.clear();
}
void KisAssistantTool::removeAssistant(KisPaintingAssistantSP assistant)
{
QList<KisPaintingAssistantSP> assistants = m_canvas->paintingAssistantsDecoration()->assistants();
KisAbstractPerspectiveGrid* grid = dynamic_cast<KisAbstractPerspectiveGrid*>(assistant.data());
if (grid) {
m_canvas->viewManager()->canvasResourceProvider()->removePerspectiveGrid(grid);
}
m_canvas->paintingAssistantsDecoration()->removeAssistant(assistant);
m_handles = m_canvas->paintingAssistantsDecoration()->handles();
KUndo2Command *removeAssistantCmd = new EditAssistantsCommand(m_canvas, m_origAssistantList, cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()), EditAssistantsCommand::REMOVE, assistants.indexOf(assistant));
m_canvas->viewManager()->undoAdapter()->addCommand(removeAssistantCmd);
m_handles = m_canvas->paintingAssistantsDecoration()->handles();
m_canvas->paintingAssistantsDecoration()->deselectAssistant();
updateToolOptionsUI();
}
......
......@@ -75,6 +75,11 @@ public:
QWidget *createOptionWidget() override;
/// clones the list of assistants
/// the originally shared handles will still be shared
/// the cloned assistants do not share any handle with the original assistants
QList<KisPaintingAssistantSP> cloneAssistantList(const QList<KisPaintingAssistantSP> &list) const;
private:
// adds and removes assistant.
// this is event is forwarded to the kis_painting_decoration class
......@@ -146,6 +151,7 @@ private:
PerspectiveAssistantEditionMode m_internalMode;
KisPaintingAssistantHandleSP m_selectedNode1, m_selectedNode2, m_higlightedNode;
int m_assistantHelperYOffset; // used by the assistant editor icons for placement on the canvas.
QList<KisPaintingAssistantSP> m_origAssistantList;
};
......