Improve scrolling. ref #831.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2018-04-26 15:08:04 +03:00
parent fd446a7c1f
commit 3d121c8247
2 changed files with 74 additions and 80 deletions

View file

@ -63,32 +63,58 @@
#include "../vmisc/vsettings.h" #include "../vmisc/vsettings.h"
#include "vabstractmainwindow.h" #include "vabstractmainwindow.h"
const int GraphicsViewZoom::duration = 300; const int GraphicsViewZoom::duration = 350;
const int GraphicsViewZoom::updateInterval = 40; const int GraphicsViewZoom::updateInterval = 30;
const qreal maxSceneSize = ((20.0 * 1000.0) / 25.4) * PrintDPI; // 20 meters in pixels const qreal maxSceneSize = ((20.0 * 1000.0) / 25.4) * PrintDPI; // 20 meters in pixels
namespace namespace
{ {
int ScrollingSteps(QWheelEvent* wheel_event) qreal ScrollingSteps(QWheelEvent* wheel_event)
{ {
SCASSERT(wheel_event != nullptr) SCASSERT(wheel_event != nullptr)
const QPoint numPixels = wheel_event->pixelDelta(); const QPoint numPixels = wheel_event->pixelDelta();
const QPoint numDegrees = wheel_event->angleDelta() / 8; const QPoint numDegrees = wheel_event->angleDelta() / 8;
int numSteps = 0; qreal numSteps = 0;
if (not numPixels.isNull()) if (not numPixels.isNull())
{ {
numSteps = wheel_event->orientation() == Qt::Vertical ? numPixels.y() : numPixels.x(); const qreal mouseScale = 2.;
numSteps = (wheel_event->orientation() == Qt::Vertical ? numPixels.y() : numPixels.x()) / mouseScale;
} }
else if (not numDegrees.isNull()) else if (not numDegrees.isNull())
{ {
numSteps = (wheel_event->orientation() == Qt::Vertical ? numDegrees.y() : numDegrees.x()) / 15; const qreal mouseScale = 45.;
numSteps = (wheel_event->orientation() == Qt::Vertical ? numDegrees.y() : numDegrees.x()) / 15. * mouseScale;
} }
return numSteps; return numSteps;
} }
//---------------------------------------------------------------------------------------------------------------------
qreal PrepareScrolling(qreal scheduledScrollings, QWheelEvent *wheel_event)
{
const qreal numSteps = ScrollingSteps(wheel_event);
if (qFuzzyIsNull(numSteps))
{
return scheduledScrollings;//Just ignore
}
if (std::signbit(scheduledScrollings) != std::signbit(numSteps))
{ // if user moved the wheel in another direction, we reset previously scheduled scalings
scheduledScrollings = numSteps;
}
else
{
scheduledScrollings += numSteps;
}
scheduledScrollings *= 1.3;
return scheduledScrollings;
}
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -163,52 +189,24 @@ void GraphicsViewZoom::set_zoom_factor_base(double value)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void GraphicsViewZoom::VerticalScrollingTime(qreal x) void GraphicsViewZoom::VerticalScrollingTime(qreal x)
{ {
Q_UNUSED(x) const qreal scroll = _numScheduledVerticalScrollings * x;
// Try to adapt scrolling to speed of rotating mouse wheel and scale factor _numScheduledVerticalScrollings -= scroll;
// Value of _numScheduledScrollings is too short, so we scale the value _view->verticalScrollBar()->setValue(qRound(_view->verticalScrollBar()->value() - scroll));
qreal scroll = static_cast<qreal>(qAbs(_numScheduledVerticalScrollings))*(10. + 10./_view->transform().m22())
/(static_cast<qreal>(duration)/static_cast<qreal>(updateInterval));
if (qAbs(scroll) < 1)
{
scroll = 1;
}
if (_numScheduledVerticalScrollings > 0)
{
scroll = scroll * -1;
}
_view->verticalScrollBar()->setValue(qRound(_view->verticalScrollBar()->value() + scroll));
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void GraphicsViewZoom::HorizontalScrollingTime(qreal x) void GraphicsViewZoom::HorizontalScrollingTime(qreal x)
{ {
Q_UNUSED(x) const qreal scroll = _numScheduledHorizontalScrollings * x;
// Try to adapt scrolling to speed of rotating mouse wheel and scale factor _numScheduledHorizontalScrollings -= scroll;
// Value of _numScheduledScrollings is too short, so we scale the value _view->horizontalScrollBar()->setValue(qRound(_view->horizontalScrollBar()->value() - scroll));
qreal scroll = static_cast<qreal>(qAbs(_numScheduledHorizontalScrollings))*(10. + 10./_view->transform().m11())
/(static_cast<qreal>(duration)/static_cast<qreal>(updateInterval));
if (qAbs(scroll) < 1)
{
scroll = 1;
}
if (_numScheduledHorizontalScrollings > 0)
{
scroll = scroll * -1;
}
_view->horizontalScrollBar()->setValue(qRound(_view->horizontalScrollBar()->value() + scroll));
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void GraphicsViewZoom::animFinished() void GraphicsViewZoom::animFinished()
{ {
_numScheduledVerticalScrollings = 0; _numScheduledVerticalScrollings = 0;
verticalScrollAnim->stop(); _numScheduledHorizontalScrollings = 0;
/* /*
* In moust cases cursor position on view doesn't change, but for scene after scrolling position will be different. * In moust cases cursor position on view doesn't change, but for scene after scrolling position will be different.
@ -257,11 +255,13 @@ bool GraphicsViewZoom::eventFilter(QObject *object, QEvent *event)
} }
else if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier) else if (QGuiApplication::keyboardModifiers() == Qt::ShiftModifier)
{ {
return StartHorizontalScrollings(wheel_event); StartHorizontalScrollings(wheel_event);
return true;
} }
else else
{ {
return StartVerticalScrollings(wheel_event); StartVerticalScrollings(wheel_event);
return true;
} }
} }
else else
@ -271,7 +271,8 @@ bool GraphicsViewZoom::eventFilter(QObject *object, QEvent *event)
return true; //ignore return true; //ignore
} }
return StartHorizontalScrollings(wheel_event); StartHorizontalScrollings(wheel_event);
return true;
} }
} }
} }
@ -314,49 +315,42 @@ void GraphicsViewZoom::FictiveSceneRect(QGraphicsScene *sc, QGraphicsView *view)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool GraphicsViewZoom::StartVerticalScrollings(QWheelEvent *wheel_event) void GraphicsViewZoom::StartVerticalScrollings(QWheelEvent *wheel_event)
{ {
const int numSteps = ScrollingSteps(wheel_event); if (not wheel_event->pixelDelta().isNull())
{ // Native scrolling animation
if (numSteps == 0) _view->verticalScrollBar()->setValue(qCeil(_view->verticalScrollBar()->value() - ScrollingSteps(wheel_event)));
animFinished();
}
else
{ {
return true;//Just ignore _numScheduledVerticalScrollings = PrepareScrolling(_numScheduledVerticalScrollings, wheel_event);
}
_numScheduledVerticalScrollings += numSteps; if (verticalScrollAnim->state() != QTimeLine::Running)
if (_numScheduledVerticalScrollings * numSteps < 0) {
{ // if user moved the wheel in another direction, we reset previously scheduled scalings verticalScrollAnim->start();
_numScheduledVerticalScrollings = numSteps; }
} }
if (verticalScrollAnim->state() != QTimeLine::Running)
{
verticalScrollAnim->start();
}
return true;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool GraphicsViewZoom::StartHorizontalScrollings(QWheelEvent *wheel_event) void GraphicsViewZoom::StartHorizontalScrollings(QWheelEvent *wheel_event)
{ {
const int numSteps = ScrollingSteps(wheel_event); if (not wheel_event->pixelDelta().isNull())
{ // Native scrolling animation
if (numSteps == 0) _view->horizontalScrollBar()->setValue(qCeil(_view->horizontalScrollBar()->value() -
ScrollingSteps(wheel_event)));
animFinished();
}
else
{ {
return true;//Just ignore _numScheduledHorizontalScrollings = PrepareScrolling(_numScheduledHorizontalScrollings, wheel_event);
}
_numScheduledHorizontalScrollings += numSteps; if (horizontalScrollAnim->state() != QTimeLine::Running)
if (_numScheduledHorizontalScrollings * numSteps < 0) {
{ // if user moved the wheel in another direction, we reset previously scheduled scalings horizontalScrollAnim->start();
_numScheduledHorizontalScrollings = numSteps; }
} }
if (horizontalScrollAnim->state() != QTimeLine::Running)
{
horizontalScrollAnim->start();
}
return true;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View file

@ -94,18 +94,18 @@ private:
QPointF target_viewport_pos; QPointF target_viewport_pos;
QTimeLine *verticalScrollAnim; QTimeLine *verticalScrollAnim;
/** @brief _numScheduledVerticalScrollings keep number scheduled vertical scrollings. */ /** @brief _numScheduledVerticalScrollings keep number scheduled vertical scrollings. */
qint32 _numScheduledVerticalScrollings; qreal _numScheduledVerticalScrollings;
QTimeLine *horizontalScrollAnim; QTimeLine *horizontalScrollAnim;
/** @brief _numScheduledHorizontalScrollings keep number scheduled horizontal scrollings. */ /** @brief _numScheduledHorizontalScrollings keep number scheduled horizontal scrollings. */
qint32 _numScheduledHorizontalScrollings; qreal _numScheduledHorizontalScrollings;
static const int duration; static const int duration;
static const int updateInterval; static const int updateInterval;
void FictiveSceneRect(QGraphicsScene *sc, QGraphicsView *view); void FictiveSceneRect(QGraphicsScene *sc, QGraphicsView *view);
bool StartVerticalScrollings(QWheelEvent* wheel_event); void StartVerticalScrollings(QWheelEvent* wheel_event);
bool StartHorizontalScrollings(QWheelEvent* wheel_event); void StartHorizontalScrollings(QWheelEvent* wheel_event);
bool GestureEvent(QGestureEvent *event); bool GestureEvent(QGestureEvent *event);
void PinchTriggered(QPinchGesture* gesture); void PinchTriggered(QPinchGesture* gesture);