Add 45-multiple degree adjustment for line, arrow and marker tools (#439)

* Add 45-multiple degree adjustment for line, arrow and marker tools

* Adjustment: Ctrl press is checked + widened functionality for two-point tools
This commit is contained in:
Nikolai Oplachko
2019-03-31 13:38:31 +03:00
committed by Dharkael
parent bd83eea7af
commit b42f1cf01d
13 changed files with 99 additions and 35 deletions

View File

@@ -16,6 +16,29 @@
// along with Flameshot. If not, see <http://www.gnu.org/licenses/>.
#include "abstracttwopointtool.h"
#include <cmath>
namespace {
const double ADJ_UNIT = std::atan(1.0);
const int DIRS_NUMBER = 4;
enum UNIT {
HORIZ_DIR = 0,
DIAG1_DIR = 1,
VERT_DIR = 2,
DIAG2_DIR = 3
};
const double ADJ_DIAG_UNIT = 2 * ADJ_UNIT;
const int DIAG_DIRS_NUMBER = 2;
enum DIAG_UNIT {
DIR1 = 0,
DIR2 = 1
};
}
AbstractTwoPointTool::AbstractTwoPointTool(QObject *parent) :
CaptureTool(parent), m_thickness(0), m_padding(0)
@@ -52,6 +75,10 @@ void AbstractTwoPointTool::drawMove(const QPoint &p) {
m_points.second = p;
}
void AbstractTwoPointTool::drawMoveWithAdjustment(const QPoint &p) {
m_points.second = m_points.first + adjustedVector(p - m_points.first);
}
void AbstractTwoPointTool::colorChanged(const QColor &c) {
m_color = c;
}
@@ -70,3 +97,39 @@ QRect AbstractTwoPointTool::backupRect(const QRect &limits) const {
r += QMargins(val, val, val, val);
return r.intersected(limits);
}
QPoint AbstractTwoPointTool::adjustedVector(QPoint v) const {
if (m_supportsOrthogonalAdj && m_supportsDiagonalAdj) {
int dir = ( static_cast<int>(round(atan2(-v.y(), v.x()) / ADJ_UNIT)) + DIRS_NUMBER ) % DIRS_NUMBER;
if (dir == UNIT::HORIZ_DIR) {
v.setY(0);
} else if (dir == UNIT::VERT_DIR) {
v.setX(0);
} else if (dir == UNIT::DIAG1_DIR) {
int newX = (v.x() - v.y()) / 2;
int newY = -newX;
v.setX(newX);
v.setY(newY);
} else {
int newX = (v.x() + v.y()) / 2;
int newY = newX;
v.setX(newX);
v.setY(newY);
}
} else if (m_supportsDiagonalAdj) {
int dir = ( static_cast<int>(round((atan2(-v.y(), v.x()) - ADJ_DIAG_UNIT / 2) / ADJ_DIAG_UNIT))
+ DIAG_DIRS_NUMBER ) % DIAG_DIRS_NUMBER;
if (dir == DIAG_UNIT::DIR1) {
int newX = (v.x() - v.y()) / 2;
int newY = -newX;
v.setX(newX);
v.setY(newY);
} else {
int newX = (v.x() + v.y()) / 2;
int newY = newX;
v.setX(newX);
v.setY(newY);
}
}
return v;
}

View File

@@ -34,6 +34,7 @@ public:
public slots:
void drawEnd(const QPoint &p) override;
void drawMove(const QPoint &p) override;
void drawMoveWithAdjustment(const QPoint &p) override;
void colorChanged(const QColor &c) override;
void thicknessChanged(const int th) override;
@@ -48,4 +49,9 @@ protected:
// use m_padding to extend the area of the backup
int m_padding;
bool m_supportsOrthogonalAdj = false;
bool m_supportsDiagonalAdj = false;
private:
QPoint adjustedVector(QPoint v) const;
};

View File

@@ -70,6 +70,8 @@ QLine getShorterLine(QPoint p1, QPoint p2, const int thickness) {
ArrowTool::ArrowTool(QObject *parent) : AbstractTwoPointTool(parent) {
m_padding = ArrowWidth / 2;
m_supportsOrthogonalAdj = true;
m_supportsDiagonalAdj = true;
}
QIcon ArrowTool::icon(const QColor &background, bool inEditor) const {

View File

@@ -135,6 +135,11 @@ public slots:
virtual void drawEnd(const QPoint &p) = 0;
// Mouse pressed and moving, called once a pixel.
virtual void drawMove(const QPoint &p) = 0;
// Called when drawMove is needed with an adjustment;
// should be overridden in case an adjustment is applicable.
virtual void drawMoveWithAdjustment(const QPoint &p) {
drawMove(p);
}
// Called when the tool is activated.
virtual void drawStart(const CaptureContext &context) = 0;
// Called right after pressign the button which activates the tool.

View File

@@ -23,7 +23,7 @@ namespace {
}
CircleTool::CircleTool(QObject *parent) : AbstractTwoPointTool(parent) {
m_supportsDiagonalAdj = true;
}
QIcon CircleTool::icon(const QColor &background, bool inEditor) const {

View File

@@ -20,18 +20,13 @@
namespace {
#define ADJ_VALUE 13
#define PADDING_VALUE 2
// Have to force horizontal position
bool needsAdjustment(const QPoint &p0, const QPoint &p1) {
return (p1.y() >= p0.y() - ADJ_VALUE) && (p1.y() <= p0.y() + ADJ_VALUE);
}
}
LineTool::LineTool(QObject *parent) : AbstractTwoPointTool(parent) {
m_supportsOrthogonalAdj = true;
m_supportsDiagonalAdj = true;
}
QIcon LineTool::icon(const QColor &background, bool inEditor) const {
@@ -67,13 +62,6 @@ void LineTool::paintMousePreview(QPainter &painter, const CaptureContext &contex
painter.drawLine(context.mousePos, context.mousePos);
}
void LineTool::drawMove(const QPoint &p) {
m_points.second = p;
if (needsAdjustment(m_points.first, m_points.second)) {
m_points.second.setY(m_points.first.y());
}
}
void LineTool::drawStart(const CaptureContext &context) {
m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE;

View File

@@ -35,7 +35,6 @@ public:
void paintMousePreview(QPainter &painter, const CaptureContext &context) override;
public slots:
void drawMove(const QPoint &p) override;
void drawStart(const CaptureContext &context) override;
void pressed(const CaptureContext &context) override;
};

View File

@@ -20,18 +20,13 @@
namespace {
#define ADJ_VALUE 14
#define PADDING_VALUE 14
// Have to force horizontal position
bool needsAdjustment(const QPoint &p0, const QPoint &p1) {
return (p1.y() >= p0.y() - ADJ_VALUE) && (p1.y() <= p0.y() + ADJ_VALUE);
}
}
MarkerTool::MarkerTool(QObject *parent) : AbstractTwoPointTool(parent) {
m_supportsOrthogonalAdj = true;
m_supportsDiagonalAdj = true;
}
QIcon MarkerTool::icon(const QColor &background, bool inEditor) const {
@@ -71,13 +66,6 @@ void MarkerTool::paintMousePreview(QPainter &painter, const CaptureContext &cont
painter.drawLine(context.mousePos, context.mousePos);
}
void MarkerTool::drawMove(const QPoint &p) {
m_points.second = p;
if (needsAdjustment(m_points.first, m_points.second)) {
m_points.second.setY(m_points.first.y());
}
}
void MarkerTool::drawStart(const CaptureContext &context) {
m_color = context.color;
m_thickness = context.thickness + PADDING_VALUE;

View File

@@ -35,7 +35,6 @@ public:
void paintMousePreview(QPainter &painter, const CaptureContext &context) override;
public slots:
void drawMove(const QPoint &p) override;
void drawStart(const CaptureContext &context) override;
void pressed(const CaptureContext &context) override;
void thicknessChanged(const int th) override;

View File

@@ -23,7 +23,7 @@ namespace {
}
RectangleTool::RectangleTool(QObject *parent) : AbstractTwoPointTool(parent) {
m_supportsDiagonalAdj = true;
}
QIcon RectangleTool::icon(const QColor &background, bool inEditor) const {

View File

@@ -23,7 +23,7 @@ namespace {
}
SelectionTool::SelectionTool(QObject *parent) : AbstractTwoPointTool(parent) {
m_supportsDiagonalAdj = true;
}
bool SelectionTool::closeOnButtonPressed() const {

View File

@@ -52,7 +52,7 @@ CaptureWidget::CaptureWidget(const uint id, const QString &savePath,
bool fullScreen, QWidget *parent) :
QWidget(parent), m_mouseIsClicked(false), m_rightClick(false),
m_newSelection(false), m_grabbing(false), m_captureDone(false),
m_previewEnabled(true), m_activeButton(nullptr),
m_previewEnabled(true), m_adjustmentButtonPressed(false), m_activeButton(nullptr),
m_activeTool(nullptr), m_toolWidget(nullptr),
m_mouseOverHandle(SelectionWidget::NO_SIDE), m_id(id)
{
@@ -398,7 +398,11 @@ void CaptureWidget::mouseMoveEvent(QMouseEvent *e) {
}
} else if (m_mouseIsClicked && m_activeTool) {
// drawing with a tool
m_activeTool->drawMove(e->pos());
if (m_adjustmentButtonPressed) {
m_activeTool->drawMoveWithAdjustment(e->pos());
} else {
m_activeTool->drawMove(e->pos());
}
update();
// Hides the buttons under the mouse. If the mouse leaves, it shows them.
if (m_buttonHandler->buttonsAreInside()) {
@@ -494,6 +498,14 @@ void CaptureWidget::keyPressEvent(QKeyEvent *e) {
m_context.selection = extendedRect(&newGeometry);
m_buttonHandler->updatePosition(m_selection->geometry());
update();
} else if (e->key() == Qt::Key_Control) {
m_adjustmentButtonPressed = true;
}
}
void CaptureWidget::keyReleaseEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Control) {
m_adjustmentButtonPressed = false;
}
}

View File

@@ -97,6 +97,7 @@ protected:
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void keyPressEvent(QKeyEvent *);
void keyReleaseEvent(QKeyEvent *);
void wheelEvent(QWheelEvent *);
void resizeEvent(QResizeEvent *);
void moveEvent(QMoveEvent *);
@@ -119,6 +120,7 @@ protected:
bool m_showInitialMsg;
bool m_captureDone;
bool m_previewEnabled;
bool m_adjustmentButtonPressed;
private:
void initContext(const QString &savePath, bool fullscreen);