Skip to content

Commit

Permalink
Zoom on cursor when it's on the canvas
Browse files Browse the repository at this point in the history
Instead of into the center, similar how it works in SAI. For people who
don't like this, there's separate center-zooming shortcuts now.
  • Loading branch information
askmeaboutlo0m committed Jul 13, 2024
1 parent 72e6e90 commit 61b3bdb
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 29 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Unreleased Version 2.2.2-pre
* Server Feature: Allow specifying idleOverride and allowWeb in session templates. Thanks MorrowShore for suggesting.
* Feature: Allow shrinking fills and magic wand selections. Thanks Meru for suggesting.
* Feature: New dialog Selection > Expand/Shrink/Feather Selection that alters selections accordingly. Thanks MorrowShore for suggesting.
* Feature: Zooming with keyboard shortcuts now zooms in on the cursor when it's pointing at the canvas. If you don't like this, there's new shortcuts that always zoom on the center, which you can bind in the preferences. Thanks Chryssabliss for suggesting.

2024-02-25 Version 2.2.2-beta.1
* Server Feature: Allow adding a message when kicking someone through the admin API.
Expand Down
17 changes: 11 additions & 6 deletions src/desktop/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4171,8 +4171,11 @@ void MainWindow::setupActions()
QAction *moveup = makeAction("moveup", tr("Move Canvas Up")).noDefaultShortcut().autoRepeat();
QAction *movedown = makeAction("movedown", tr("Move Canvas Down")).noDefaultShortcut().autoRepeat();
QAction *zoomin = makeAction("zoomin", tr("Zoom &In")).icon("zoom-in").shortcut(QKeySequence::ZoomIn).autoRepeat();
QAction *zoomincenter = makeAction("zoomincenter", tr("Zoom In On Center")).noDefaultShortcut().autoRepeat();
QAction *zoomout = makeAction("zoomout", tr("Zoom &Out")).icon("zoom-out").shortcut(QKeySequence::ZoomOut).autoRepeat();
QAction *zoomorig = makeAction("zoomone", tr("&Normal Size")).icon("zoom-original").shortcut(QKeySequence("ctrl+0"));
QAction *zoomoutcenter = makeAction("zoomoutcenter", tr("Zoom Out From Center")).noDefaultShortcut().autoRepeat();
QAction *zoomorig = makeAction("zoomone", tr("&Reset Zoom")).icon("zoom-original").shortcut(QKeySequence("ctrl+0"));
QAction *zoomorigcenter = makeAction("zoomonecenter", tr("Reset Zoom At Center")).noDefaultShortcut();
QAction *zoomfit = makeAction("zoomfit", tr("&Fit Page")).icon("zoom-select").noDefaultShortcut();
QAction *zoomfitwidth = makeAction("zoomfitwidth", tr("Fit Page &Width")).icon("zoom-fit-width").noDefaultShortcut();
QAction *zoomfitheight = makeAction("zoomfitheight", tr("Fit Page &Height")).icon("zoom-fit-height").noDefaultShortcut();
Expand Down Expand Up @@ -4262,13 +4265,15 @@ void MainWindow::setupActions()
[this](bool showSelectionMask) {
m_canvasView->setShowSelectionMask(showSelectionMask);
});
// clang-format off

m_canvasView->connectActions(
{moveleft, moveright, moveup, movedown, zoomin, zoomout, zoomorig,
zoomfit, zoomfitwidth, zoomfitheight, rotateorig, rotatecw, rotateccw,
viewflip, viewmirror, showgrid, showusermarkers, showusernames,
showuserlayers, showuseravatars, evadeusercursors});
{moveleft, moveright, moveup, movedown,
zoomin, zoomincenter, zoomout, zoomoutcenter,
zoomorig, zoomorigcenter, zoomfit, zoomfitwidth,
zoomfitheight, rotateorig, rotatecw, rotateccw,
viewflip, viewmirror, showgrid, showusermarkers,
showusernames, showuserlayers, showuseravatars, evadeusercursors});
// clang-format off

#ifdef SINGLE_MAIN_WINDOW
connect(fittoscreen, &QAction::triggered, this, &MainWindow::refitWindow);
Expand Down
2 changes: 2 additions & 0 deletions src/desktop/scene/canvasscene.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ class CanvasScene final : public QGraphicsScene {
void setOutlineSquare(bool square);
void setOutlineWidth(qreal width);
void setOutlineVisibleInMode(bool visibleInMode);
bool isCursorOnCanvas() const { return m_cursorOnCanvas; }
void setCursorOnCanvas(bool onCanvas);
const QPointF &cursorPos() const { return m_cursorPos; }
void setCursorPos(const QPointF &pos);
#ifdef HAVE_EMULATED_BITMAP_CURSOR
void setCursor(const QCursor &cursor);
Expand Down
33 changes: 30 additions & 3 deletions src/desktop/scene/canvasview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,34 @@ void CanvasView::scrollStepDown()
scrollBy(0, verticalScrollBar()->singleStep());
}

void CanvasView::zoomin()
void CanvasView::zoominCenter()
{
zoomStepsAt(1, mapToCanvas(rect().center()));
}

void CanvasView::zoomout()
void CanvasView::zoominCursor()
{
if(m_scene && m_scene->isCursorOnCanvas()) {
zoomStepsAt(1, mapToCanvas(mapFromScene(m_scene->cursorPos())));
} else {
zoominCenter();
}
}

void CanvasView::zoomoutCenter()
{
zoomStepsAt(-1, mapToCanvas(rect().center()));
}

void CanvasView::zoomoutCursor()
{
if(m_scene && m_scene->isCursorOnCanvas()) {
zoomStepsAt(-1, mapToCanvas(mapFromScene(m_scene->cursorPos())));
} else {
zoomoutCenter();
}
}

void CanvasView::zoomTo(const QRect &rect, int steps)
{
if(rect.width() < 15 || rect.height() < 15 || steps < 0) {
Expand Down Expand Up @@ -477,11 +495,20 @@ void CanvasView::setZoom(qreal zoom)
setZoomAt(zoom, mapToCanvas(rect().center()));
}

void CanvasView::resetZoom()
void CanvasView::resetZoomCenter()
{
setZoom(1.0);
}

void CanvasView::resetZoomCursor()
{
if(m_scene && m_scene->isCursorOnCanvas()) {
setZoomAt(1.0, mapToCanvas(mapFromScene(m_scene->cursorPos())));
} else {
resetZoomCenter();
}
}

void CanvasView::setZoomAt(qreal zoom, const QPointF &point)
{
qreal newZoom = qBound(zoomMin, zoom, zoomMax);
Expand Down
12 changes: 6 additions & 6 deletions src/desktop/scene/canvasview.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ public slots:
//! Set the zoom factor in percents, centered on the given point
void setZoomAt(qreal zoom, const QPointF &point);

void resetZoom();
void resetZoomCenter();
void resetZoomCursor();

//! Set the rotation angle in degrees
void setRotation(qreal angle);
Expand Down Expand Up @@ -205,11 +206,10 @@ public slots:
void zoomSteps(int steps);
void zoomStepsAt(int steps, const QPointF &point);

//! Increase zoom factor
void zoomin();

//! Decrease zoom factor
void zoomout();
void zoominCenter();
void zoominCursor();
void zoomoutCenter();
void zoomoutCursor();

//! Zoom the view it's filled by the given rectangle
//! If the rectangle is very small, or steps are negative, just zoom by that
Expand Down
21 changes: 17 additions & 4 deletions src/desktop/scene/scenewrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,23 @@ void SceneWrapper::connectActions(const Actions &actions)
connect(
actions.movedown, &QAction::triggered, m_view,
&CanvasView::scrollStepDown);
connect(actions.zoomin, &QAction::triggered, m_view, &CanvasView::zoomin);
connect(actions.zoomout, &QAction::triggered, m_view, &CanvasView::zoomout);
connect(
actions.zoomorig, &QAction::triggered, m_view, &CanvasView::resetZoom);
actions.zoomin, &QAction::triggered, m_view, &CanvasView::zoominCursor);
connect(
actions.zoomincenter, &QAction::triggered, m_view,
&CanvasView::zoominCenter);
connect(
actions.zoomout, &QAction::triggered, m_view,
&CanvasView::zoomoutCursor);
connect(
actions.zoomoutcenter, &QAction::triggered, m_view,
&CanvasView::zoomoutCenter);
connect(
actions.zoomorig, &QAction::triggered, m_view,
&CanvasView::resetZoomCursor);
connect(
actions.zoomorigcenter, &QAction::triggered, m_view,
&CanvasView::resetZoomCenter);
connect(
actions.zoomfit, &QAction::triggered, m_view, &CanvasView::zoomToFit);
connect(
Expand Down Expand Up @@ -423,7 +436,7 @@ void SceneWrapper::connectToolSettings(docks::ToolSettings *toolSettings)
tools::ZoomSettings *zoomSettings = toolSettings->zoomSettings();
connect(
zoomSettings, &tools::ZoomSettings::resetZoom, m_view,
&CanvasView::resetZoom);
&CanvasView::resetZoomCenter);
connect(
zoomSettings, &tools::ZoomSettings::fitToWindow, m_view,
&CanvasView::zoomToFit);
Expand Down
27 changes: 24 additions & 3 deletions src/desktop/view/canvascontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,16 @@ void CanvasController::setZoomAt(qreal zoom, const QPointF &point)
}
}

void CanvasController::resetZoom()
void CanvasController::resetZoomCenter()
{
setZoom(1.0);
}

void CanvasController::resetZoomCursor()
{
setZoomAt(1.0, cursorPosOrCenter());
}

void CanvasController::zoomTo(const QRect &rect, int steps)
{
if(steps < 0 || rect.width() < ZOOM_TO_MINIMUM_DIMENSION ||
Expand All @@ -187,16 +192,26 @@ void CanvasController::zoomToFit()
setZoomToFit(Qt::Horizontal | Qt::Vertical);
}

void CanvasController::zoomIn()
void CanvasController::zoomInCenter()
{
zoomSteps(1);
}

void CanvasController::zoomOut()
void CanvasController::zoomInCursor()
{
zoomStepsAt(1, cursorPosOrCenter());
}

void CanvasController::zoomOutCenter()
{
zoomSteps(-1);
}

void CanvasController::zoomOutCursor()
{
zoomStepsAt(-1, cursorPosOrCenter());
}

void CanvasController::zoomToFitWidth()
{
setZoomToFit(Qt::Horizontal);
Expand Down Expand Up @@ -2320,6 +2335,12 @@ void CanvasController::translateByViewTransformOffset(
}
}

QPointF CanvasController::cursorPosOrCenter() const
{
return mapPointToCanvasF(
m_scene->isCursorOnCanvas() ? m_scene->cursorPos() : viewCenterF());
}

QString CanvasController::getZoomNoticeText() const
{
return QCoreApplication::translate("widgets::CanvasView", "Zoom: %1%")
Expand Down
13 changes: 10 additions & 3 deletions src/desktop/view/canvascontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,25 @@ class CanvasController : public QObject {
void scrollByF(qreal x, qreal y);
void setZoom(qreal zoom);
void setZoomAt(qreal zoom, const QPointF &pos);
void resetZoom();
void resetZoomCenter();
void resetZoomCursor();
void zoomTo(const QRect &rect, int steps);
void zoomToFit();
void zoomToFitHeight();
void zoomToFitWidth();
void zoomIn();
void zoomOut();
void zoomInCenter();
void zoomInCursor();
void zoomOutCenter();
void zoomOutCursor();
void zoomSteps(int steps);
void zoomStepsAt(int steps, const QPointF &point);
void setRotation(qreal degrees);
void resetRotation();
void resetRotationCursor();
void rotateStepClockwise();
void rotateStepClockwiseCursor();
void rotateStepCounterClockwise();
void rotateStepCounterClockwiseCursor();
void setFlip(bool flip);
void setMirror(bool mirror);

Expand Down Expand Up @@ -312,6 +318,7 @@ class CanvasController : public QObject {
QPointF viewToCanvasOffset() const;
QPointF viewTransformOffset() const;
void translateByViewTransformOffset(QTransform &prev, QTransform &cur);
QPointF cursorPosOrCenter() const;

QString getZoomNoticeText() const;
QString getRotationNoticeText() const;
Expand Down
2 changes: 2 additions & 0 deletions src/desktop/view/canvasscene.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ class CanvasScene final : public QGraphicsScene {
void setMaskPreview(const QPoint &pos, const QImage &mask);
void setPathPreview(const QPainterPath &path);

bool isCursorOnCanvas() const { return m_cursorOnCanvas; }
void setCursorOnCanvas(bool cursorOnCanvas);
const QPointF &cursorPos() const { return m_cursorPos; }
void setCursorPos(const QPointF &cursorPos);
void setOutline(
bool visibleInMode, const QPointF &pos, qreal rotation,
Expand Down
3 changes: 3 additions & 0 deletions src/desktop/view/canvaswrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ class CanvasWrapper {
QAction *moveup;
QAction *movedown;
QAction *zoomin;
QAction *zoomincenter;
QAction *zoomout;
QAction *zoomoutcenter;
QAction *zoomorig;
QAction *zoomorigcenter;
QAction *zoomfit;
QAction *zoomfitwidth;
QAction *zoomfitheight;
Expand Down
17 changes: 13 additions & 4 deletions src/desktop/view/viewwrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,22 @@ void ViewWrapper::connectActions(const Actions &actions)
&CanvasView::scrollStepDown);
connect(
actions.zoomin, &QAction::triggered, m_controller,
&CanvasController::zoomIn);
&CanvasController::zoomInCursor);
connect(
actions.zoomincenter, &QAction::triggered, m_controller,
&CanvasController::zoomInCenter);
connect(
actions.zoomout, &QAction::triggered, m_controller,
&CanvasController::zoomOut);
&CanvasController::zoomOutCursor);
connect(
actions.zoomoutcenter, &QAction::triggered, m_controller,
&CanvasController::zoomOutCenter);
connect(
actions.zoomorig, &QAction::triggered, m_controller,
&CanvasController::resetZoom);
&CanvasController::resetZoomCursor);
connect(
actions.zoomorigcenter, &QAction::triggered, m_controller,
&CanvasController::resetZoomCenter);
connect(
actions.zoomfit, &QAction::triggered, m_controller,
&CanvasController::zoomToFit);
Expand Down Expand Up @@ -418,7 +427,7 @@ void ViewWrapper::connectToolSettings(docks::ToolSettings *toolSettings)
tools::ZoomSettings *zoomSettings = toolSettings->zoomSettings();
connect(
zoomSettings, &tools::ZoomSettings::resetZoom, m_controller,
&CanvasController::resetZoom);
&CanvasController::resetZoomCenter);
connect(
zoomSettings, &tools::ZoomSettings::fitToWindow, m_controller,
&CanvasController::zoomToFit);
Expand Down

0 comments on commit 61b3bdb

Please sign in to comment.