Cleanup of ZoomControl and fix of Zoom and Scroll

presentation
Febbe 6 years ago committed by Fabian Keßler
parent 988dcf5091
commit 3dcda37291
  1. 197
      src/control/zoom/ZoomControl.cpp
  2. 174
      src/control/zoom/ZoomControl.h
  3. 7
      src/gui/XournalView.cpp
  4. 95
      src/gui/inputdevices/TouchInputHandler.cpp
  5. 24
      src/gui/inputdevices/TouchInputHandler.h
  6. 4
      src/gui/toolbarMenubar/ToolZoomSlider.cpp
  7. 48
      src/util/Point.h

@ -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<double> 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<double> 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<double> 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<double> {
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<double> scrollPos) {
this->scrollPosition = (scrollPos + this->zoomWidgetPos) / this->zoom;
}
/**
* Zoom to correct position on zooming
*/
auto ZoomControl::getScrollPositionAfterZoom() const -> std::tuple<double, double> {
auto ZoomControl::getScrollPositionAfterZoom() const -> utl::Point<double> {
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<double>& 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();
}

@ -11,23 +11,22 @@
#pragma once
#include <string>
#include <tuple>
#include <vector>
#include <gtk/gtk.h>
#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<double> 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<double> 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<double> 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<double> scrollPos);
/**
* Zoom to correct position on zooming
*/
std::tuple<double, double> getScrollPositionAfterZoom() const;
/// Zoom to correct position on zooming
utl::Point<double> getScrollPositionAfterZoom() const;
/**
* Get visible rect on xournal view, for Zoom Gesture
*/
/// Get visible rect on xournal view, for Zoom Gesture
Rectangle<double> 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<ZoomListener*> 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<double> zoomWidgetPos;
/**
* Scroll position to scale
*/
double scrollPositionX = 0;
/// Scroll position (top left corner of view) to scale
utl::Point<double> 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<double> 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;
};

@ -499,9 +499,10 @@ void XournalView::zoomChanged() {
if (zoom->isZoomPresentationMode() || zoom->isZoomFitMode()) {
scrollTo(currentPage);
} else {
std::tuple<double, double> 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

@ -4,8 +4,6 @@
#include "TouchInputHandler.h"
#include <cmath>
#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>{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<double, double> 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};
}

@ -16,28 +16,24 @@
#include <vector>
#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<double> lastZoomScrollCenter{};
utl::Point<double> priLastAbs{-1.0, -1.0};
utl::Point<double> secLastAbs{-1.0, -1.0};
utl::Point<double> priLastRel{-1.0, -1.0};
utl::Point<double> secLastRel{-1.0, -1.0};
private:
void sequenceStart(InputEvent const& event);

@ -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;

@ -0,0 +1,48 @@
/*
* Xournal++
*
* Range
*
* @author Xournal++ Team
* https://github.com/xournalpp/xournalpp
*
* @license GNU GPLv2 or later
*/
#pragma once
#include <cmath>
#include <tuple>
namespace utl {
template <typename T>
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
Loading…
Cancel
Save