diff --git a/src/control/zoom/ZoomControl.cpp b/src/control/zoom/ZoomControl.cpp index c159523f..52e3a579 100644 --- a/src/control/zoom/ZoomControl.cpp +++ b/src/control/zoom/ZoomControl.cpp @@ -8,38 +8,25 @@ #include "gui/XournalView.h" #include "gui/widgets/XournalWidget.h" -ZoomControl::ZoomControl() { - this->zoomStep = DEFAULT_ZOOM_STEP * this->zoom100Value; - this->zoomStepScroll = DEFAULT_ZOOM_STEP_SCROLL * this->zoom100Value; - this->zoomMax = DEFAULT_ZOOM_MAX * this->zoom100Value; - this->zoomMin = DEFAULT_ZOOM_MIN * this->zoom100Value; -} - -ZoomControl::~ZoomControl() = default; - -void ZoomControl::zoomOneStep(bool zoomIn, double x, double y) { +void ZoomControl::zoomOneStep(ZoomDirection direction, utl::Point zoomCenter) { if (this->zoomPresentationMode) { return; } + this->setZoomFitMode(false); - startZoomSequence(x, y); - - if (this->zoomFitMode) { - this->setZoomFitMode(false); - } - - double newZoom = NAN; - if (zoomIn) { - newZoom = this->zoom + this->zoomStep; - } else { - newZoom = this->zoom - this->zoomStep; - } + startZoomSequence(zoomCenter); + double newZoom = (direction == ZOOM_IN) ? this->zoom + this->zoomStep : this->zoom - this->zoomStep; this->zoomSequenceChange(newZoom, false); - endZoomSequence(); } -void ZoomControl::zoomScroll(bool zoomIn, double x, double y) { +void ZoomControl::zoomOneStep(ZoomDirection direction) { + Rectangle rect = getVisibleRect(); + zoomOneStep(direction, {rect.x + rect.width / 2.0, rect.y + rect.height / 2.0}); +} + + +void ZoomControl::zoomScroll(ZoomDirection zoomIn, utl::Point zoomCenter) { if (this->zoomPresentationMode) { return; } @@ -48,49 +35,29 @@ void ZoomControl::zoomScroll(bool zoomIn, double x, double y) { this->setZoomFitMode(false); } - if (this->zoomSequenceStart == -1 || scrollCursorPositionX != x || scrollCursorPositionY != y) { - scrollCursorPositionX = x; - scrollCursorPositionY = y; - startZoomSequence(x, y); + if (this->zoomSequenceStart == -1 || scrollCursorPosition != zoomCenter) { + scrollCursorPosition = zoomCenter; + startZoomSequence(zoomCenter); } - double newZoom = NAN; - if (zoomIn) { - newZoom = this->zoom + this->zoomStepScroll; - } else { - newZoom = this->zoom - this->zoomStepScroll; - } + double newZoom = this->zoom + (zoomIn ? this->zoomStepScroll : -this->zoomStepScroll); this->zoomSequenceChange(newZoom, false); } -/** - * Call this before any zoom is done, it saves the current page and position - * - * @param centerX Zoom Center X (use -1 for center of the visible rect) - * @param centerY Zoom Center Y (use -1 for center of the visible rect) - */ -void ZoomControl::startZoomSequence(double centerX, double centerY) { +void ZoomControl::startZoomSequence() { Rectangle rect = getVisibleRect(); - if (centerX == -1 || centerY == -1) { - this->zoomWidgetPosX = rect.width / 2; - this->zoomWidgetPosY = rect.height / 2; - } else { - this->zoomWidgetPosX = centerX - rect.x; - this->zoomWidgetPosY = centerY - rect.y; - } + startZoomSequence({rect.x + rect.width / 2.0, rect.y + rect.height / 2.0}); +} - this->scrollPositionX = (rect.x + this->zoomWidgetPosX) / this->zoom; - this->scrollPositionY = (rect.y + this->zoomWidgetPosY) / this->zoom; +void ZoomControl::startZoomSequence(utl::Point zoomCenter) { + auto const& rect = getVisibleRect(); + auto const& view_pos = utl::Point{rect.x, rect.y}; + this->zoomWidgetPos = zoomCenter - view_pos; + this->scrollPosition = (view_pos + this->zoomWidgetPos) / this->zoom; this->zoomSequenceStart = this->zoom; } -/** - * Change the zoom within a Zoom sequence (startZoomSequence() / endZoomSequence()) - * - * @param zoom Current zoom value - * @param relative If the zoom is relative to the start value (for Gesture) - */ void ZoomControl::zoomSequenceChange(double zoom, bool relative) { if (relative && this->zoomSequenceStart != -1) { zoom *= zoomSequenceStart; @@ -99,54 +66,39 @@ void ZoomControl::zoomSequenceChange(double zoom, bool relative) { setZoom(zoom); } -/** - * Clear all stored data from startZoomSequence() - */ void ZoomControl::endZoomSequence() { - scrollPositionX = -1; - scrollPositionY = -1; - + scrollPosition = {-1, -1}; zoomSequenceStart = -1; } -/** - * Get visible rect on xournal view, for Zoom Gesture - */ auto ZoomControl::getVisibleRect() -> Rectangle { GtkWidget* widget = view->getWidget(); Layout* layout = gtk_xournal_get_layout(widget); return layout->getVisibleRect(); } -void ZoomControl::setScrollPositionAfterZoom(double x, double y) { - this->scrollPositionX = (x + this->zoomWidgetPosX) / this->zoom; - this->scrollPositionY = (y + this->zoomWidgetPosY) / this->zoom; +void ZoomControl::setScrollPositionAfterZoom(utl::Point scrollPos) { + this->scrollPosition = (scrollPos + this->zoomWidgetPos) / this->zoom; } -/** - * Zoom to correct position on zooming - */ -auto ZoomControl::getScrollPositionAfterZoom() const -> std::tuple { +auto ZoomControl::getScrollPositionAfterZoom() const -> utl::Point { if (this->zoomSequenceStart == -1) { - return std::make_tuple(-1, -1); + return {-1, -1}; } - double x = (this->scrollPositionX * this->zoom) - this->zoomWidgetPosX; - double y = (this->scrollPositionY * this->zoom) - this->zoomWidgetPosY; - return std::make_tuple(x, y); + return (this->scrollPosition * this->zoom) - this->zoomWidgetPos; } -void ZoomControl::addZoomListener(ZoomListener* listener) { this->listener.push_back(listener); } +void ZoomControl::addZoomListener(ZoomListener* l) { this->listener.emplace_back(l); } -void ZoomControl::initZoomHandler(GtkWidget* widget, XournalView* view, Control* control) { +void ZoomControl::initZoomHandler(GtkWidget* widget, XournalView* v, Control* c) { + this->control = c; + this->view = v; g_signal_connect(widget, "scroll_event", G_CALLBACK(onScrolledwindowMainScrollEvent), this); - g_signal_connect(widget, "size-allocate", G_CALLBACK(onWidgetSizeChangedEvent), this); - registerListener(control); - this->view = view; - this->control = control; + registerListener(this->control); } void ZoomControl::fireZoomChanged() { @@ -173,17 +125,18 @@ auto ZoomControl::getZoom() const -> double { return this->zoom; } auto ZoomControl::getZoomReal() const -> double { return this->zoom / this->zoom100Value; } -void ZoomControl::setZoom(double zoom) { - this->zoom = zoom; +void ZoomControl::setZoom(double zoomI) { + this->zoom = zoomI; fireZoomChanged(); } -void ZoomControl::setZoom100Value(double zoom) { - this->zoom100Value = zoom; - setZoomStep(this->zoomStepReal); - setZoomStepScroll(this->zoomStepScrollReal); - this->zoomMax = this->zoomMaxReal * zoom; - this->zoomMin = this->zoomMinReal * zoom; +void ZoomControl::setZoom100Value(double zoom100Val) { + auto setWithRelZoom = [zoomOld = this->zoom100Value, zoom100Val](double& val) { val = val / zoomOld * zoom100Val; }; + setWithRelZoom(this->zoomStep); + setWithRelZoom(this->zoomStepScroll); + setWithRelZoom(this->zoomMax); + setWithRelZoom(this->zoomMin); + this->zoom100Value = zoom100Val; fireZoomRangeValueChanged(); } @@ -194,8 +147,7 @@ auto ZoomControl::updateZoomFitValue(const Rectangle& widget_rect, size_ pageNo = view->getCurrentPage(); } XojPageView* page = view->getViewFor(pageNo); - if (!page) { - // no page + if (!page) { // no page return false; } @@ -236,8 +188,6 @@ auto ZoomControl::updateZoomPresentationValue(size_t pageNo) -> bool { return true; } -auto ZoomControl::getZoomPresentationValue() const -> double { return this->zoomPresentationValue; } - auto ZoomControl::getZoom100Value() const -> double { return this->zoom100Value; } void ZoomControl::zoom100() { @@ -249,14 +199,14 @@ void ZoomControl::zoom100() { this->setZoomFitMode(false); } - startZoomSequence(-1, -1); + startZoomSequence(); this->zoomSequenceChange(this->zoom100Value, false); endZoomSequence(); } void ZoomControl::zoomFit() { if (this->zoomFitMode && !this->zoomPresentationMode && this->zoom != this->zoomFitValue) { - startZoomSequence(-1, -1); + startZoomSequence(); this->zoomSequenceChange(this->zoomFitValue, false); endZoomSequence(); } @@ -264,7 +214,7 @@ void ZoomControl::zoomFit() { void ZoomControl::zoomPresentation() { if (this->zoomPresentationMode && this->zoom != this->zoomPresentationValue) { - startZoomSequence(-1, -1); + startZoomSequence(); this->zoomSequenceChange(this->zoomPresentationValue, false); endZoomSequence(); } @@ -293,42 +243,14 @@ void ZoomControl::setZoomPresentationMode(bool isZoomPresentationMode) { auto ZoomControl::isZoomPresentationMode() const -> bool { return this->zoomPresentationMode; } -auto ZoomControl::getZoomStep() const -> double { return this->zoomStep; } - -auto ZoomControl::getZoomStepReal() const -> double { return this->zoomStepReal; } - void ZoomControl::setZoomStep(double zoomStep) { - this->zoomStepReal = zoomStep; this->zoomStep = zoomStep * this->zoom100Value; } -auto ZoomControl::getZoomStepScroll() const -> double { return this->zoomStepScroll; } - -auto ZoomControl::getZoomStepScrollReal() const -> double { return this->zoomStepScrollReal; } - void ZoomControl::setZoomStepScroll(double zoomStep) { - this->zoomStepScrollReal = zoomStep; this->zoomStepScroll = zoomStep * this->zoom100Value; } -auto ZoomControl::getZoomMax() const -> double { return this->zoomMax; } - -auto ZoomControl::getZoomMaxReal() const -> double { return this->zoomMaxReal; } - -void ZoomControl::setZoomMax(double zoomMax) { - this->zoomMaxReal = zoomMax; - this->zoomMax = zoomMax * this->zoom100Value; -} - -auto ZoomControl::getZoomMin() const -> double { return this->zoomMin; } - -auto ZoomControl::getZoomMinReal() const -> double { return this->zoomMinReal; } - -void ZoomControl::setZoomMin(double zoomMin) { - this->zoomMinReal = zoomMin; - this->zoomMin = zoomMin * this->zoom100Value; -} - void ZoomControl::pageSizeChanged(size_t page) { updateZoomPresentationValue(page); updateZoomFitValue(page); @@ -348,27 +270,16 @@ auto ZoomControl::onScrolledwindowMainScrollEvent(GtkWidget* widget, GdkEventScr } if (state & GDK_CONTROL_MASK) { - GtkWidget* topLevel = gtk_widget_get_toplevel(widget); - int wx = 0; - int wy = 0; - gtk_widget_translate_coordinates(widget, topLevel, 0, 0, &wx, &wy); - - if (event->direction == GDK_SCROLL_UP || (event->direction == GDK_SCROLL_SMOOTH && event->delta_y < 0)) { - zoom->zoomScroll(ZOOM_IN, event->x, event->y); - } else if (event->direction == GDK_SCROLL_DOWN || - (event->direction == GDK_SCROLL_SMOOTH && event->delta_y > 0)) { - zoom->zoomScroll(ZOOM_OUT, event->x, event->y); - } - return true; - } - - // TODO(fabian): Disabling scroll here is maybe a bit hacky - if (zoom->isZoomPresentationMode()) { - // disable scroll while presentationMode + auto direction = + (event->direction == GDK_SCROLL_UP || (event->direction == GDK_SCROLL_SMOOTH && event->delta_y < 0)) ? + ZOOM_IN : + ZOOM_OUT; + zoom->zoomScroll(direction, {event->x, event->y}); return true; } - return false; + // TODO(unknown): Disabling scroll here is maybe a bit hacky find a better way + return zoom->isZoomPresentationMode(); } diff --git a/src/control/zoom/ZoomControl.h b/src/control/zoom/ZoomControl.h index 1441aeb1..98552999 100644 --- a/src/control/zoom/ZoomControl.h +++ b/src/control/zoom/ZoomControl.h @@ -11,23 +11,22 @@ #pragma once -#include -#include #include #include #include "model/DocumentListener.h" +#include "Point.h" #include "Rectangle.h" #include "XournalType.h" -#define DEFAULT_ZOOM_MAX 7 -#define DEFAULT_ZOOM_MIN 0.3 -#define DEFAULT_ZOOM_STEP 0.1 -#define DEFAULT_ZOOM_STEP_SCROLL 0.01 -#define ZOOM_IN true -#define ZOOM_OUT false +constexpr auto DEFAULT_ZOOM_MAX{7}; +constexpr auto DEFAULT_ZOOM_MIN{0.3}; +constexpr auto DEFAULT_ZOOM_STEP{0.1}; +constexpr auto DEFAULT_ZOOM_STEP_SCROLL{0.01}; + +enum ZoomDirection : bool { ZOOM_OUT = false, ZOOM_IN = true }; class XournalView; class Control; @@ -37,26 +36,25 @@ class DocumentListener; class ZoomControl: public DocumentListener { public: - ZoomControl(); - virtual ~ZoomControl(); + ZoomControl() = default; + virtual ~ZoomControl() = default; /** * Zoom one step * - * @param zoomIn zoom in or out - * @param x x position of focus to zoom - * @param y y position of focus to zoom + * @param direction direction to zoom in or out + * @param zoomCenter position of zoom focus */ - void zoomOneStep(bool zoomIn, double x = -1, double y = -1); + void zoomOneStep(ZoomDirection direction, utl::Point zoomCenter); + void zoomOneStep(ZoomDirection direction); /** * Zoom one step * - * @param zoomIn zoom in or out - * @param x x position of focus to zoom - * @param y y position of focus to zoom + * @param direction to zoom in or out + * @param zoomCenter position of zoom focus */ - void zoomScroll(bool zoomIn, double x, double y); + void zoomScroll(ZoomDirection direction, utl::Point zoomCenter); /** * Zoom so that the page fits the current size of the window @@ -91,17 +89,17 @@ public: * Use startZoomSequence() / zoomSequnceChange() / endZoomSequence() to preserve position * e.g. use zoomOneStep function * - * @param zoom zoom value depending zoom100Value + * @param zoomI zoom value depending zoom100Value */ - void setZoom(double zoom); + void setZoom(double zoomI); /** * Updates the when dpi is changed. * updates zoomMax, zoomMin, zoomStepBig, zoomStepScroll * - * @param zoom zoom value depending zoom100Value + * @param zoom100Val zoom value depending zoom100Value */ - void setZoom100Value(double zoom); + void setZoom100Value(double zoom100Val); /** * @return zoom value for zoom 100% depending zoom100Value @@ -121,7 +119,6 @@ public: double getZoomFitValue() const; bool updateZoomPresentationValue(size_t pageNo = 0); - double getZoomPresentationValue() const; void addZoomListener(ZoomListener* listener); @@ -130,10 +127,16 @@ public: /** * Call this before any zoom is done, it saves the current page and position * - * @param centerX Zoom Center X (use -1 for center of the visible rect) - * @param centerY Zoom Center Y (use -1 for center of the visible rect) + * @param zoomCenter position of zoom focus + */ + + void startZoomSequence(utl::Point zoomCenter); + + /** + * Call this before any zoom is done, it saves the current page and position + * zooms to the center of the visible rect */ - void startZoomSequence(double centerX, double centerY); + void startZoomSequence(); /** * Change the zoom within a Zoom sequence (startZoomSequence() / endZoomSequence()) @@ -143,48 +146,27 @@ public: */ void zoomSequenceChange(double zoom, bool relative); - /** - * Clear all stored data from startZoomSequence() - */ + /// Clear all stored data from startZoomSequence() void endZoomSequence(); - /** - * Update the scroll position manually - */ - void setScrollPositionAfterZoom(double x, double y); + /// Update the scroll position manually + void setScrollPositionAfterZoom(utl::Point scrollPos); - /** - * Zoom to correct position on zooming - */ - std::tuple getScrollPositionAfterZoom() const; + /// Zoom to correct position on zooming + utl::Point getScrollPositionAfterZoom() const; - /** - * Get visible rect on xournal view, for Zoom Gesture - */ + /// Get visible rect on xournal view, for Zoom Gesture Rectangle getVisibleRect(); - double getZoomStep() const; - double getZoomStepReal() const; void setZoomStep(double zoomStep); - double getZoomStepScroll() const; - double getZoomStepScrollReal() const; void setZoomStepScroll(double zoomStep); - double getZoomMax() const; - double getZoomMaxReal() const; - void setZoomMax(double zoomMax); - - double getZoomMin() const; - double getZoomMinReal() const; - void setZoomMin(double zoomMin); - protected: void fireZoomChanged(); void fireZoomRangeValueChanged(); void pageSizeChanged(size_t page); - // void pageChanged(size_t page); void pageSelected(size_t page); static bool onScrolledwindowMainScrollEvent(GtkWidget* widget, GdkEventScroll* event, ZoomControl* zoom); @@ -197,7 +179,6 @@ private: private: XournalView* view = nullptr; Control* control = nullptr; - std::vector listener; /** @@ -205,100 +186,47 @@ private: * depends dpi (REAL_PERCENTAGE_VALUE * zoom100Value) */ double zoom = 1.0; - - /** - * for zoom sequence start zoom value - * depends dpi (REAL_PERCENTAGE_VALUE * zoom100Value) - */ - double lastZoomValue = 1.0; - bool zoomFitMode = false; bool zoomPresentationMode = false; - /** - * Zoom value for 100% depends on the dpi - */ + /// Zoom value for 100% depends on the dpi double zoom100Value = 1.0; double zoomFitValue = 1.0; double zoomPresentationValue = 1.0; - /** - * Base zoom on start, for relative zoom (Gesture) - */ + /// Base zoom on start, for relative zoom (Gesture) double zoomSequenceStart = -1; - /** - * Zoom point on widget, will not be zoomed! - */ - double zoomWidgetPosX = 0; - - /** - * Zoom point on widget, will not be zoomed! - */ - double zoomWidgetPosY = 0; + /// Zoom center pos on view, will not be zoomed! + utl::Point zoomWidgetPos; - /** - * Scroll position to scale - */ - double scrollPositionX = 0; + /// Scroll position (top left corner of view) to scale + utl::Point scrollPosition; - /** - * Scroll position to scale - */ - double scrollPositionY = 0; - - /** - * Cursorposition x for Ctrl + Scroll - */ - double scrollCursorPositionX = 0; - - /** - * Cursorposition y for Ctrl + Scroll - */ - double scrollCursorPositionY = 0; + /// Cursorposition x for Ctrl + Scroll + utl::Point scrollCursorPosition; /** * Zoomstep value for Ctrl - and Zoom In and Out Button - * depends dpi (REAL_PERCENTAGE_VALUE * zoom100Value) - */ - double zoomStep = 0; - - /** - * Real zoomstep value for Ctrl + and Zoom In and Out Button + * depends on dpi (REAL_PERCENTAGE_VALUE * zoom100Value) */ - double zoomStepReal = DEFAULT_ZOOM_STEP; + double zoomStep = DEFAULT_ZOOM_STEP; /** * Zoomstep value for Ctrl-Scroll zooming - * depends dpi (REAL_PERCENTAGE_VALUE * zoom100Value) - */ - double zoomStepScroll = 0; - - /** - * Real zoomstep value for Ctrl-Scroll zooming + * depends on dpi (REAL_PERCENTAGE_VALUE * zoom100Value) */ - double zoomStepScrollReal = DEFAULT_ZOOM_STEP_SCROLL; + double zoomStepScroll = DEFAULT_ZOOM_STEP_SCROLL; /** * Zoom maximal value - * depends dpi (REAL_PERCENTAGE_VALUE * zoom100Value) + * depends on dpi (REAL_PERCENTAGE_VALUE * zoom100Value) */ - double zoomMax = 0; - - /** - * Real zoom maximal value - */ - double zoomMaxReal = DEFAULT_ZOOM_MAX; + double zoomMax = DEFAULT_ZOOM_MAX; /** * Zoom mininmal value - * depends dpi (REAL_PERCENTAGE_VALUE * zoom100Value) - */ - double zoomMin = 0; - - /** - * Real zoom mininmal value - * depends dpi (REAL_PERCENTAGE_VALUE * zoom100Value) + * depends on dpi (REAL_PERCENTAGE_VALUE * zoom100Value) */ - double zoomMinReal = DEFAULT_ZOOM_MIN; + double zoomMin = DEFAULT_ZOOM_MIN; }; diff --git a/src/gui/XournalView.cpp b/src/gui/XournalView.cpp index 54420397..2a0469f0 100644 --- a/src/gui/XournalView.cpp +++ b/src/gui/XournalView.cpp @@ -499,9 +499,10 @@ void XournalView::zoomChanged() { if (zoom->isZoomPresentationMode() || zoom->isZoomFitMode()) { scrollTo(currentPage); } else { - std::tuple pos = zoom->getScrollPositionAfterZoom(); - if (std::get<0>(pos) != -1 && std::get<1>(pos) != -1) { - layout->scrollAbs(std::get<0>(pos), std::get<1>(pos)); + auto pos = zoom->getScrollPositionAfterZoom(); + if (pos.x != -1 && pos.y != -1) { + // Todo: This could be one source of all evil: + layout->scrollAbs(pos.x, pos.y); } } // move this somewhere else maybe diff --git a/src/gui/inputdevices/TouchInputHandler.cpp b/src/gui/inputdevices/TouchInputHandler.cpp index 8e5bcaf0..af0d598a 100644 --- a/src/gui/inputdevices/TouchInputHandler.cpp +++ b/src/gui/inputdevices/TouchInputHandler.cpp @@ -4,8 +4,6 @@ #include "TouchInputHandler.h" -#include - #include "InputContext.h" TouchInputHandler::TouchInputHandler(InputContext* inputContext): AbstractInputHandler(inputContext) {} @@ -64,39 +62,34 @@ auto TouchInputHandler::handleImpl(InputEvent const& event) -> bool { void TouchInputHandler::sequenceStart(InputEvent const& event) { if (event.sequence == this->primarySequence) { - this->priLastAbsX = event.absoluteX; - this->priLastAbsY = event.absoluteY; - this->priLastRelX = event.relativeX; - this->priLastRelY = event.relativeY; + this->priLastAbs = {event.absoluteX, event.absoluteY}; + this->priLastRel = {event.relativeX, event.relativeY}; } else { - this->secLastAbsX = event.absoluteX; - this->secLastAbsY = event.absoluteY; - this->secLastRelX = event.relativeX; - this->secLastRelY = event.relativeY; + this->secLastAbs = {event.absoluteX, event.absoluteY}; + this->secLastRel = {event.relativeX, event.relativeY}; } } void TouchInputHandler::scrollMotion(InputEvent const& event) { - double offsetX = NAN; - double offsetY = NAN; // Will only be called if there is a single sequence (zooming handles two sequences) - if (event.sequence == this->primarySequence) { - offsetX = event.absoluteX - this->priLastAbsX; - offsetY = event.absoluteY - this->priLastAbsY; - this->priLastAbsX = event.absoluteX; - this->priLastAbsY = event.absoluteY; - } else { - offsetX = event.absoluteX - this->secLastAbsX; - offsetY = event.absoluteY - this->secLastAbsY; - this->secLastAbsX = event.absoluteX; - this->secLastAbsY = event.absoluteY; - } + auto offset = [&]() { + auto absolutePoint = utl::Point{event.absoluteX, event.absoluteY}; + if (event.sequence == this->primarySequence) { + auto offset = absolutePoint - this->priLastAbs; + this->priLastAbs = absolutePoint; + return offset; + } else { + auto offset = absolutePoint - this->secLastAbs; + this->secLastAbs = absolutePoint; + return offset; + } + }(); GtkAdjustment* h = this->inputContext->getView()->getScrollHandling()->getHorizontal(); - gtk_adjustment_set_value(h, gtk_adjustment_get_value(h) - offsetX); + gtk_adjustment_set_value(h, gtk_adjustment_get_value(h) - offset.x); GtkAdjustment* v = this->inputContext->getView()->getScrollHandling()->getVertical(); - gtk_adjustment_set_value(v, gtk_adjustment_get_value(v) - offsetY); + gtk_adjustment_set_value(v, gtk_adjustment_get_value(v) - offset.y); } void TouchInputHandler::zoomStart() { @@ -112,13 +105,10 @@ void TouchInputHandler::zoomStart() { inputContext->getSettings()->getAddHorizontalSpaceAmount() : 0; - double centerX = (this->priLastRelX + this->secLastRelX) / 2.0 - hPadding; - double centerY = (this->priLastRelY + this->secLastRelY) / 2.0 - vPadding; + auto center = (this->priLastRel + this->secLastRel) / 2.0 - utl::Point{double(hPadding), double(vPadding)}; - this->startZoomDistance = std::sqrt(std::pow(this->priLastAbsX - this->secLastAbsX, 2.0) + - std::pow(this->priLastAbsY - this->secLastAbsY, 2.0)); - lastZoomScrollCenterX = (this->priLastAbsX + this->secLastAbsX) / 2.0; - lastZoomScrollCenterY = (this->priLastAbsY + this->secLastAbsY) / 2.0; + this->startZoomDistance = this->priLastAbs.distance(this->secLastAbs); + lastZoomScrollCenter = (this->priLastAbs + this->secLastAbs) / 2.0; ZoomControl* zoomControl = this->inputContext->getView()->getControl()->getZoomControl(); @@ -130,36 +120,29 @@ void TouchInputHandler::zoomStart() { Rectangle zoomSequenceRectangle = zoomControl->getVisibleRect(); - zoomControl->startZoomSequence(centerX - zoomSequenceRectangle.x, centerY - zoomSequenceRectangle.y); + zoomControl->startZoomSequence(center); } void TouchInputHandler::zoomMotion(InputEvent const& event) { if (event.sequence == this->primarySequence) { - this->priLastAbsX = event.absoluteX; - this->priLastAbsY = event.absoluteY; + this->priLastAbs = {event.absoluteX, event.absoluteY}; } else { - this->secLastAbsX = event.absoluteX; - this->secLastAbsY = event.absoluteY; + this->secLastAbs = {event.absoluteX, event.absoluteY}; } - double sqDistance = std::sqrt(std::pow(this->priLastAbsX - this->secLastAbsX, 2.0) + - std::pow(this->priLastAbsY - this->secLastAbsY, 2.0)); + double sqDistance = this->priLastAbs.distance(this->secLastAbs); double zoom = sqDistance / this->startZoomDistance; ZoomControl* zoomControl = this->inputContext->getView()->getControl()->getZoomControl(); zoomControl->zoomSequenceChange(zoom, true); - double centerX = (this->priLastAbsX + this->secLastAbsX) / 2.0; - double centerY = (this->priLastAbsY + this->secLastAbsY) / 2.0; + auto center = (this->priLastAbs + this->secLastAbs) / 2; + auto lastScrollPosition = zoomControl->getScrollPositionAfterZoom(); + auto offset = lastScrollPosition - (center - lastZoomScrollCenter); - std::tuple lastScrollPosition = zoomControl->getScrollPositionAfterZoom(); - double offsetX = std::get<0>(lastScrollPosition) - (centerX - lastZoomScrollCenterX); - double offsetY = std::get<1>(lastScrollPosition) - (centerY - lastZoomScrollCenterY); - - zoomControl->setScrollPositionAfterZoom(offsetX, offsetY); - lastZoomScrollCenterX = centerX; - lastZoomScrollCenterY = centerY; + zoomControl->setScrollPositionAfterZoom(offset); + lastZoomScrollCenter = center; } void TouchInputHandler::zoomEnd() { @@ -172,16 +155,10 @@ void TouchInputHandler::onUnblock() { this->secondarySequence = nullptr; this->startZoomDistance = 0.0; - this->lastZoomScrollCenterX = 0.0; - this->lastZoomScrollCenterY = 0.0; - - this->priLastAbsX = -1.0; - this->priLastAbsY = -1.0; - this->secLastAbsX = -1.0; - this->secLastAbsY = -1.0; - - this->priLastRelX = -1.0; - this->priLastRelY = -1.0; - this->secLastRelX = -1.0; - this->secLastRelY = -1.0; + this->lastZoomScrollCenter = {}; + + priLastAbs = {-1.0, -1.0}; + secLastAbs = {-1.0, -1.0}; + priLastRel = {-1.0, -1.0}; + secLastRel = {-1.0, -1.0}; } diff --git a/src/gui/inputdevices/TouchInputHandler.h b/src/gui/inputdevices/TouchInputHandler.h index aac2a528..388aa4e1 100644 --- a/src/gui/inputdevices/TouchInputHandler.h +++ b/src/gui/inputdevices/TouchInputHandler.h @@ -16,28 +16,24 @@ #include #include "AbstractInputHandler.h" +#include "Point.h" #include "XournalType.h" class InputContext; class TouchInputHandler: public AbstractInputHandler { private: - GdkEventSequence* primarySequence = nullptr; - GdkEventSequence* secondarySequence = nullptr; + GdkEventSequence* primarySequence{}; + GdkEventSequence* secondarySequence{}; double startZoomDistance = 0.0; - double lastZoomScrollCenterX = 0.0; - double lastZoomScrollCenterY = 0.0; - - double priLastAbsX = -1.0; - double priLastAbsY = -1.0; - double secLastAbsX = -1.0; - double secLastAbsY = -1.0; - - double priLastRelX = -1.0; - double priLastRelY = -1.0; - double secLastRelX = -1.0; - double secLastRelY = -1.0; + utl::Point lastZoomScrollCenter{}; + + utl::Point priLastAbs{-1.0, -1.0}; + utl::Point secLastAbs{-1.0, -1.0}; + + utl::Point priLastRel{-1.0, -1.0}; + utl::Point secLastRel{-1.0, -1.0}; private: void sequenceStart(InputEvent const& event); diff --git a/src/gui/toolbarMenubar/ToolZoomSlider.cpp b/src/gui/toolbarMenubar/ToolZoomSlider.cpp index 68c88cc0..18a9d859 100644 --- a/src/gui/toolbarMenubar/ToolZoomSlider.cpp +++ b/src/gui/toolbarMenubar/ToolZoomSlider.cpp @@ -29,7 +29,7 @@ void ToolZoomSlider::sliderChanged(GtkRange* range, ToolZoomSlider* self) { auto ToolZoomSlider::sliderButtonPress(GtkRange* range, GdkEvent* event, ToolZoomSlider* self) -> bool { if (!self->sliderChangingBySliderDrag && !self->zoom->isZoomPresentationMode()) { self->zoom->setZoomFitMode(false); - self->zoom->startZoomSequence(-1, -1); + self->zoom->startZoomSequence(); self->sliderChangingBySliderDrag = true; } return false; @@ -45,7 +45,7 @@ auto ToolZoomSlider::sliderHoverScroll(GtkWidget* range, GdkEventScroll* event, gint64 now = g_get_monotonic_time(); if (now > self->sliderHoverScrollLastTime + 500) { self->zoom->setZoomFitMode(false); - self->zoom->startZoomSequence(-1, -1); + self->zoom->startZoomSequence(); } self->sliderChangingBySliderHoverScroll = true; self->sliderHoverScrollLastTime = now; diff --git a/src/util/Point.h b/src/util/Point.h new file mode 100644 index 00000000..ffe2f494 --- /dev/null +++ b/src/util/Point.h @@ -0,0 +1,48 @@ +/* + * Xournal++ + * + * Range + * + * @author Xournal++ Team + * https://github.com/xournalpp/xournalpp + * + * @license GNU GPLv2 or later + */ + +#pragma once + +#include +#include + +namespace utl { + +template +struct Point { + + Point() = default; + Point(T x, T y): x(x), y(y) {} + + [[maybe_unused]] double distance(Point p) { return std::hypot(p.x - this->x, p.y - this->y); } + + [[maybe_unused]] Point operator-(Point p) const { return {this->x - p.x, this->y - p.y}; } + [[maybe_unused]] Point& operator-=(Point p) { return *this = *this - p; } + + [[maybe_unused]] Point operator+(Point p) const { return {this->x + p.x, this->y + p.y}; } + [[maybe_unused]] Point& operator+=(Point p) { return *this = *this + p; } + + [[maybe_unused]] Point operator/(T k) const { return {this->x / k, this->y / k}; } + [[maybe_unused]] Point& operator/=(T k) { return *this = *this / k; } + + [[maybe_unused]] Point operator*(T k) const { return {this->x * k, this->y * k}; } + [[maybe_unused]] Point& operator*=(T k) { return *this = *this * k; } + + [[maybe_unused]] friend bool operator==(Point const& lhs, Point const& rhs) { + return std::tie(lhs.x, lhs.y) == std::tie(rhs.x, rhs.y); + } + + [[maybe_unused]] friend bool operator!=(Point const& lhs, Point const& rhs) { return !(lhs == rhs); } + + T x{}; + T y{}; +}; +} // namespace utl