Commit 8bfeb51a authored by Emmet O'Neill's avatar Emmet O'Neill

Constrain Assistant Editors to Viewport.

This commit constrains the position of each assistant editor widget
within the bounds of the viewport, allowing the user to manipulate
assistants that would typically be off-screen (for example: a distant
and subtle vanishing point).
parent eda2fca1
......@@ -151,6 +151,11 @@ KisCoordinatesConverter::~KisCoordinatesConverter()
delete m_d;
}
QSizeF KisCoordinatesConverter::getCanvasWidgetSize() const
{
return m_d->canvasWidgetSize;
}
void KisCoordinatesConverter::setCanvasWidgetSize(QSizeF size)
{
m_d->canvasWidgetSize = size;
......@@ -294,7 +299,7 @@ QPoint KisCoordinatesConverter::resetRotation(QPointF center)
return m_d->documentOffset.toPoint();
}
QTransform KisCoordinatesConverter::imageToWidgetTransform() const{
QTransform KisCoordinatesConverter::imageToWidgetTransform() const {
return m_d->imageToDocument * m_d->documentToFlake * m_d->flakeToWidget;
}
......@@ -310,8 +315,7 @@ QTransform KisCoordinatesConverter::flakeToWidgetTransform() const {
return m_d->flakeToWidget;
}
QTransform KisCoordinatesConverter::documentToWidgetTransform() const
{
QTransform KisCoordinatesConverter::documentToWidgetTransform() const {
return m_d->documentToFlake * m_d->flakeToWidget;
}
......
......@@ -59,6 +59,8 @@ public:
KisCoordinatesConverter();
~KisCoordinatesConverter() override;
QSizeF getCanvasWidgetSize() const;
void setCanvasWidgetSize(QSizeF size);
void setDevicePixelRatio(qreal value);
void setImage(KisImageWSP image);
......
......@@ -341,6 +341,22 @@ void KisPaintingAssistant::addHandle(KisPaintingAssistantHandleSP handle, Handle
handle.data()->setType(type);
}
QPointF KisPaintingAssistant::viewportConstrainedEditorPosition(const KisCoordinatesConverter* converter, const QSize editorSize)
{
QPointF editorDocumentPos = getEditorPosition();
QPointF editorWidgetPos = converter->documentToWidgetTransform().map(editorDocumentPos);
QSizeF canvasSize = converter->getCanvasWidgetSize();
const int padding = 16;
editorWidgetPos.rx() = qBound(0.0,
editorWidgetPos.x(),
canvasSize.width() - (editorSize.width() + padding));
editorWidgetPos.ry() = qBound(0.0,
editorWidgetPos.y(),
canvasSize.height() - (editorSize.height() + padding));
return converter->widgetToDocument(editorWidgetPos);
}
void KisPaintingAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool useCache, KisCanvas2* canvas, bool assistantVisible, bool previewVisible)
{
......
......@@ -111,25 +111,21 @@ public:
*/
virtual QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) = 0;
virtual void endStroke() { }
virtual QPointF buttonPosition() const = 0;
virtual QPointF getEditorPosition() const = 0; // Returns editor widget position in document-space coordinates.
virtual int numHandles() const = 0;
void replaceHandle(KisPaintingAssistantHandleSP _handle, KisPaintingAssistantHandleSP _with);
void addHandle(KisPaintingAssistantHandleSP handle, HandleType type);
QColor effectiveAssistantColor() const;
QPointF viewportConstrainedEditorPosition(const KisCoordinatesConverter* converter, const QSize editorSize);
/// should this assistant use a custom color for the display? global color will be used if this is false
QColor effectiveAssistantColor() const;
bool useCustomColor();
void setUseCustomColor(bool useCustomColor);
/// getter and setter for assistant's custom color
void setAssistantCustomColor(QColor color);
QColor assistantCustomColor();
void setAssistantGlobalColorCache(const QColor &color);
virtual void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter *converter, bool cached = true,KisCanvas2 *canvas=0, bool assistantVisible=true, bool previewVisible=true);
void uncache();
const QList<KisPaintingAssistantHandleSP>& handles() const;
......
......@@ -446,14 +446,11 @@ void KisPaintingAssistantsDecoration::drawEditorWidget(KisPaintingAssistantSP as
return;
}
QTransform initialTransform = converter->documentToWidgetTransform();
AssistantEditorData toolData; // shared const data for positioning and sizing
// We are going to put all of the assistant actions below the bounds of the assistant
// so they are out of the way
// assistant->buttonPosition() gets the center X/Y position point
QPointF actionsPosition = initialTransform.map(assistant->buttonPosition());
QTransform initialTransform = converter->documentToWidgetTransform();
AssistantEditorData toolData; // shared const data for positioning and sizing
QPointF actionsPosition = initialTransform.map(assistant->viewportConstrainedEditorPosition(converter, toolData.boundingSize));
QPointF iconMovePosition(actionsPosition + toolData.moveIconPosition);
QPointF iconSnapPosition(actionsPosition + toolData.snapIconPosition);
......@@ -466,13 +463,13 @@ void KisPaintingAssistantsDecoration::drawEditorWidget(KisPaintingAssistantSP as
gc.setRenderHint(QPainter::Antialiasing);
QPainterPath bgPath;
bgPath.addRoundedRect(QRectF(actionsBGRectangle.x(), actionsBGRectangle.y(), 110, 40), 6, 6);
bgPath.addRoundedRect(QRectF(actionsBGRectangle.x(), actionsBGRectangle.y(), toolData.boundingSize.width(), toolData.boundingSize.height()), 6, 6);
QPen stroke(QColor(60, 60, 60, 80), 2);
// if the assistant is selected, make outline stroke fatter and use theme's highlight color
// for better visual feedback
if (selectedAssistant()) { // there might not be a selected assistant, so do not seg fault
if (assistant->buttonPosition() == selectedAssistant()->buttonPosition()) {
if (assistant->getEditorPosition() == selectedAssistant()->getEditorPosition()) {
stroke.setWidth(4);
stroke.setColor(qApp->palette().color(QPalette::Highlight));
}
......
......@@ -43,6 +43,7 @@ struct AssistantEditorData {
const QPointF moveIconPosition = QPointF(15, 15);
const QPointF snapIconPosition = QPointF(54, 20);
const QPointF deleteIconPosition = QPointF(83, 18);
const QSize boundingSize = QSize(110, 40);
};
/**
......
......@@ -173,7 +173,7 @@ QRect ConcentricEllipseAssistant::boundingRect() const
}
}
QPointF ConcentricEllipseAssistant::buttonPosition() const
QPointF ConcentricEllipseAssistant::getEditorPosition() const
{
return (*handles()[0] + *handles()[1]) * 0.5;
}
......
......@@ -32,7 +32,7 @@ public:
ConcentricEllipseAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 3; }
bool isAssistantComplete() const override;
......
......@@ -145,7 +145,7 @@ QRect EllipseAssistant::boundingRect() const
}
}
QPointF EllipseAssistant::buttonPosition() const
QPointF EllipseAssistant::getEditorPosition() const
{
return (*handles()[0] + *handles()[1]) * 0.5;
}
......
......@@ -31,7 +31,7 @@ public:
EllipseAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 3; }
bool isAssistantComplete() const override;
......
......@@ -203,7 +203,7 @@ QRect FisheyePointAssistant::boundingRect() const
}
}
QPointF FisheyePointAssistant::buttonPosition() const
QPointF FisheyePointAssistant::getEditorPosition() const
{
return (*handles()[0] + *handles()[1]) * 0.5;
}
......
......@@ -37,7 +37,7 @@ public:
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
//virtual void endStroke();
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 3; }
bool isAssistantComplete() const override;
......
......@@ -137,7 +137,7 @@ void InfiniteRulerAssistant::drawCache(QPainter& gc, const KisCoordinatesConvert
}
QPointF InfiniteRulerAssistant::buttonPosition() const
QPointF InfiniteRulerAssistant::getEditorPosition() const
{
return (*handles()[0]);
}
......
......@@ -38,7 +38,7 @@ public:
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
//virtual void endStroke();
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 2; }
bool isAssistantComplete() const override;
......
......@@ -144,7 +144,7 @@ void ParallelRulerAssistant::drawCache(QPainter& gc, const KisCoordinatesConvert
}
QPointF ParallelRulerAssistant::buttonPosition() const
QPointF ParallelRulerAssistant::getEditorPosition() const
{
return (*handles()[0] + *handles()[1]) * 0.5;
}
......
......@@ -38,7 +38,7 @@ public:
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
//virtual void endStroke();
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 2; }
bool isAssistantComplete() const override;
......
......@@ -343,7 +343,7 @@ void PerspectiveAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter
}
QPointF PerspectiveAssistant::buttonPosition() const
QPointF PerspectiveAssistant::getEditorPosition() const
{
QPointF centroid(0, 0);
for (int i = 0; i < 4; ++i) {
......
......@@ -36,7 +36,7 @@ public:
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
void endStroke() override;
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 4; }
void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached = true,KisCanvas2* canvas=0, bool assistantVisible=true, bool previewVisible=true) override;
......
......@@ -143,7 +143,7 @@ void RulerAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *conv
drawPath(gc, path, isSnappingActive());
}
QPointF RulerAssistant::buttonPosition() const
QPointF RulerAssistant::getEditorPosition() const
{
return (*handles()[0] + *handles()[1]) * 0.5;
}
......
......@@ -32,7 +32,7 @@ public:
RulerAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 2; }
bool isAssistantComplete() const override;
......
......@@ -205,7 +205,7 @@ void SplineAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *con
}
QPointF SplineAssistant::buttonPosition() const
QPointF SplineAssistant::getEditorPosition() const
{
return B(0.5, *handles()[0], *handles()[2], *handles()[3], *handles()[1]);
}
......
......@@ -30,7 +30,7 @@ public:
SplineAssistant();
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 4; }
bool isAssistantComplete() const override;
......
......@@ -252,7 +252,7 @@ void VanishingPointAssistant::drawCache(QPainter& gc, const KisCoordinatesConver
drawPath(gc, path, isSnappingActive());
}
QPointF VanishingPointAssistant::buttonPosition() const
QPointF VanishingPointAssistant::getEditorPosition() const
{
return (*handles()[0]);
}
......
......@@ -49,7 +49,7 @@ public:
KisPaintingAssistantSP clone(QMap<KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP> &handleMap) const override;
QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override;
//virtual void endStroke();
QPointF buttonPosition() const override;
QPointF getEditorPosition() const override;
int numHandles() const override { return 1; }
float referenceLineDensity();
......
......@@ -275,13 +275,13 @@ void KisAssistantTool::beginPrimaryAction(KoPointerEvent *event)
} else if (m_handleDrag == assistant->handles()[1]) {
m_dragStart = *assistant->handles()[0];
} else if (m_handleDrag == assistant->handles()[2]) {
m_dragStart = assistant->buttonPosition();
m_dragStart = assistant->getEditorPosition();
m_radius = QLineF(m_dragStart, *assistant->handles()[0]);
m_snapIsRadial = true;
}
} else {
m_dragStart = assistant->buttonPosition();
m_dragStart = assistant->getEditorPosition();
m_snapIsRadial = false;
}
}
......@@ -300,22 +300,21 @@ void KisAssistantTool::beginPrimaryAction(KoPointerEvent *event)
m_assistantDrag.clear();
Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) {
// This code contains the click event behavior.
QTransform initialTransform = m_canvas->coordinatesConverter()->documentToWidgetTransform();
QPointF actionsPosition = initialTransform.map(assistant->buttonPosition());
AssistantEditorData editorShared; // shared position data between assistant tool and decoration
const KisCoordinatesConverter *converter = m_canvas->coordinatesConverter();
// This code contains the click event behavior.
QTransform initialTransform = converter->documentToWidgetTransform();
QPointF actionsPosition = initialTransform.map(assistant->viewportConstrainedEditorPosition(converter, editorShared.boundingSize));
// for UI editor widget controls with move, show, and delete -- disregard document transforms like rotating and mirroring.
// otherwise the UI controls get awkward to use when they are at 45 degree angles or the order of controls gets flipped backwards
QPointF uiMousePosition = initialTransform.map( canvasDecoration->snapToGuide(event, QPointF(), false));
AssistantEditorData editorShared; // shared position data between assistant tool and decoration
QPointF uiMousePosition = initialTransform.map(canvasDecoration->snapToGuide(event, QPointF(), false));
QPointF iconMovePosition(actionsPosition + editorShared.moveIconPosition);
QPointF iconSnapPosition(actionsPosition + editorShared.snapIconPosition);
QPointF iconDeletePosition(actionsPosition + editorShared.deleteIconPosition);
QRectF deleteRect(iconDeletePosition, QSizeF(editorShared.deleteIconSize, editorShared.deleteIconSize));
QRectF visibleRect(iconSnapPosition, QSizeF(editorShared.snapIconSize, editorShared.snapIconSize));
QRectF moveRect(iconMovePosition, QSizeF(editorShared.moveIconSize, editorShared.moveIconSize));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment