1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWidgets module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include <QPointer>
41 #include <QObject>
42 #include <QtCore/qmath.h>
43 
44 #include "qscrollerproperties.h"
45 #include "private/qscrollerproperties_p.h"
46 
47 QT_BEGIN_NAMESPACE
48 
49 static QScrollerPropertiesPrivate *userDefaults = nullptr;
50 static QScrollerPropertiesPrivate *systemDefaults = nullptr;
51 
defaults()52 QScrollerPropertiesPrivate *QScrollerPropertiesPrivate::defaults()
53 {
54     if (!systemDefaults) {
55         QScrollerPropertiesPrivate spp;
56         spp.mousePressEventDelay = qreal(0.25);
57         spp.dragStartDistance = qreal(5.0 / 1000);
58         spp.dragVelocitySmoothingFactor = qreal(0.8);
59         spp.axisLockThreshold = qreal(0);
60         spp.scrollingCurve.setType(QEasingCurve::OutQuad);
61         spp.decelerationFactor = qreal(0.125);
62         spp.minimumVelocity = qreal(50.0 / 1000);
63         spp.maximumVelocity = qreal(500.0 / 1000);
64         spp.maximumClickThroughVelocity = qreal(66.5 / 1000);
65         spp.acceleratingFlickMaximumTime = qreal(1.25);
66         spp.acceleratingFlickSpeedupFactor = qreal(3.0);
67         spp.snapPositionRatio = qreal(0.5);
68         spp.snapTime = qreal(0.3);
69         spp.overshootDragResistanceFactor = qreal(0.5);
70         spp.overshootDragDistanceFactor = qreal(1);
71         spp.overshootScrollDistanceFactor = qreal(0.5);
72         spp.overshootScrollTime = qreal(0.7);
73         spp.hOvershootPolicy = QScrollerProperties::OvershootWhenScrollable;
74         spp.vOvershootPolicy = QScrollerProperties::OvershootWhenScrollable;
75         spp.frameRate = QScrollerProperties::Standard;
76 
77         systemDefaults = new QScrollerPropertiesPrivate(spp);
78     }
79     return new QScrollerPropertiesPrivate(userDefaults ? *userDefaults : *systemDefaults);
80 }
81 
82 /*!
83     \class QScrollerProperties
84     \brief The QScrollerProperties class stores the settings for a QScroller.
85     \since 4.8
86 
87     \inmodule QtWidgets
88 
89     The QScrollerProperties class stores the parameters used by QScroller.
90 
91     The default settings are platform dependent so that Qt emulates the
92     platform behaviour for kinetic scrolling.
93 
94     As a convention the QScrollerProperties are in physical units (meter,
95     seconds) and are converted by QScroller using the current DPI.
96 
97     \sa QScroller
98 */
99 
100 /*!
101     Constructs new scroller properties.
102 */
QScrollerProperties()103 QScrollerProperties::QScrollerProperties()
104     : d(QScrollerPropertiesPrivate::defaults())
105 {
106 }
107 
108 /*!
109     Constructs a copy of \a sp.
110 */
QScrollerProperties(const QScrollerProperties & sp)111 QScrollerProperties::QScrollerProperties(const QScrollerProperties &sp)
112     : d(new QScrollerPropertiesPrivate(*sp.d))
113 {
114 }
115 
116 /*!
117     Assigns \a sp to these scroller properties and returns a reference to these scroller properties.
118 */
operator =(const QScrollerProperties & sp)119 QScrollerProperties &QScrollerProperties::operator=(const QScrollerProperties &sp)
120 {
121     *d.data() = *sp.d.data();
122     return *this;
123 }
124 
125 /*!
126     Destroys the scroller properties.
127 */
~QScrollerProperties()128 QScrollerProperties::~QScrollerProperties()
129 {
130 }
131 
132 /*!
133     Returns \c true if these scroller properties are equal to \a sp; otherwise returns \c false.
134 */
operator ==(const QScrollerProperties & sp) const135 bool QScrollerProperties::operator==(const QScrollerProperties &sp) const
136 {
137     return *d.data() == *sp.d.data();
138 }
139 
140 /*!
141     Returns \c true if these scroller properties are different from \a sp; otherwise returns \c false.
142 */
operator !=(const QScrollerProperties & sp) const143 bool QScrollerProperties::operator!=(const QScrollerProperties &sp) const
144 {
145     return !(*d.data() == *sp.d.data());
146 }
147 
operator ==(const QScrollerPropertiesPrivate & p) const148 bool QScrollerPropertiesPrivate::operator==(const QScrollerPropertiesPrivate &p) const
149 {
150     bool same = true;
151     same &= (mousePressEventDelay == p.mousePressEventDelay);
152     same &= (dragStartDistance == p.dragStartDistance);
153     same &= (dragVelocitySmoothingFactor == p.dragVelocitySmoothingFactor);
154     same &= (axisLockThreshold == p.axisLockThreshold);
155     same &= (scrollingCurve == p.scrollingCurve);
156     same &= (decelerationFactor == p.decelerationFactor);
157     same &= (minimumVelocity == p.minimumVelocity);
158     same &= (maximumVelocity == p.maximumVelocity);
159     same &= (maximumClickThroughVelocity == p.maximumClickThroughVelocity);
160     same &= (acceleratingFlickMaximumTime == p.acceleratingFlickMaximumTime);
161     same &= (acceleratingFlickSpeedupFactor == p.acceleratingFlickSpeedupFactor);
162     same &= (snapPositionRatio == p.snapPositionRatio);
163     same &= (snapTime == p.snapTime);
164     same &= (overshootDragResistanceFactor == p.overshootDragResistanceFactor);
165     same &= (overshootDragDistanceFactor == p.overshootDragDistanceFactor);
166     same &= (overshootScrollDistanceFactor == p.overshootScrollDistanceFactor);
167     same &= (overshootScrollTime == p.overshootScrollTime);
168     same &= (hOvershootPolicy == p.hOvershootPolicy);
169     same &= (vOvershootPolicy == p.vOvershootPolicy);
170     same &= (frameRate == p.frameRate);
171     return same;
172 }
173 
174 /*!
175      Sets the scroller properties for all new QScrollerProperties objects to \a sp.
176 
177      Use this function to override the platform default properties returned by the default
178      constructor. If you only want to change the scroller properties of a single scroller, use
179      QScroller::setScrollerProperties()
180 
181      \note Calling this function will not change the content of already existing
182      QScrollerProperties objects.
183 
184      \sa unsetDefaultScrollerProperties()
185 */
setDefaultScrollerProperties(const QScrollerProperties & sp)186 void QScrollerProperties::setDefaultScrollerProperties(const QScrollerProperties &sp)
187 {
188     if (!userDefaults)
189         userDefaults = new QScrollerPropertiesPrivate(*sp.d);
190     else
191         *userDefaults = *sp.d;
192 }
193 
194 /*!
195      Sets the scroller properties returned by the default constructor back to the platform default
196      properties.
197 
198      \sa setDefaultScrollerProperties()
199 */
unsetDefaultScrollerProperties()200 void QScrollerProperties::unsetDefaultScrollerProperties()
201 {
202     delete userDefaults;
203     userDefaults = nullptr;
204 }
205 
206 /*!
207     Query the \a metric value of the scroller properties.
208 
209     \sa setScrollMetric(), ScrollMetric
210 */
scrollMetric(ScrollMetric metric) const211 QVariant QScrollerProperties::scrollMetric(ScrollMetric metric) const
212 {
213     switch (metric) {
214     case MousePressEventDelay:          return d->mousePressEventDelay;
215     case DragStartDistance:             return d->dragStartDistance;
216     case DragVelocitySmoothingFactor:   return d->dragVelocitySmoothingFactor;
217     case AxisLockThreshold:             return d->axisLockThreshold;
218     case ScrollingCurve:                return d->scrollingCurve;
219     case DecelerationFactor:            return d->decelerationFactor;
220     case MinimumVelocity:               return d->minimumVelocity;
221     case MaximumVelocity:               return d->maximumVelocity;
222     case MaximumClickThroughVelocity:   return d->maximumClickThroughVelocity;
223     case AcceleratingFlickMaximumTime:  return d->acceleratingFlickMaximumTime;
224     case AcceleratingFlickSpeedupFactor:return d->acceleratingFlickSpeedupFactor;
225     case SnapPositionRatio:             return d->snapPositionRatio;
226     case SnapTime:                      return d->snapTime;
227     case OvershootDragResistanceFactor: return d->overshootDragResistanceFactor;
228     case OvershootDragDistanceFactor:   return d->overshootDragDistanceFactor;
229     case OvershootScrollDistanceFactor: return d->overshootScrollDistanceFactor;
230     case OvershootScrollTime:           return d->overshootScrollTime;
231     case HorizontalOvershootPolicy:     return QVariant::fromValue(d->hOvershootPolicy);
232     case VerticalOvershootPolicy:       return QVariant::fromValue(d->vOvershootPolicy);
233     case FrameRate:                     return QVariant::fromValue(d->frameRate);
234     case ScrollMetricCount:             break;
235     }
236     return QVariant();
237 }
238 
239 /*!
240     Set a specific value of the \a metric ScrollerMetric to \a value.
241 
242     \sa scrollMetric(), ScrollMetric
243 */
setScrollMetric(ScrollMetric metric,const QVariant & value)244 void QScrollerProperties::setScrollMetric(ScrollMetric metric, const QVariant &value)
245 {
246     switch (metric) {
247     case MousePressEventDelay:          d->mousePressEventDelay = value.toReal(); break;
248     case DragStartDistance:             d->dragStartDistance = value.toReal(); break;
249     case DragVelocitySmoothingFactor:   d->dragVelocitySmoothingFactor = qBound(qreal(0), value.toReal(), qreal(1)); break;
250     case AxisLockThreshold:             d->axisLockThreshold = qBound(qreal(0), value.toReal(), qreal(1)); break;
251     case ScrollingCurve:                d->scrollingCurve = value.toEasingCurve(); break;
252     case DecelerationFactor:            d->decelerationFactor = value.toReal(); break;
253     case MinimumVelocity:               d->minimumVelocity = value.toReal(); break;
254     case MaximumVelocity:               d->maximumVelocity = value.toReal(); break;
255     case MaximumClickThroughVelocity:   d->maximumClickThroughVelocity = value.toReal(); break;
256     case AcceleratingFlickMaximumTime:  d->acceleratingFlickMaximumTime = value.toReal(); break;
257     case AcceleratingFlickSpeedupFactor:d->acceleratingFlickSpeedupFactor = value.toReal(); break;
258     case SnapPositionRatio:             d->snapPositionRatio = qBound(qreal(0), value.toReal(), qreal(1)); break;
259     case SnapTime:                      d->snapTime = value.toReal(); break;
260     case OvershootDragResistanceFactor: d->overshootDragResistanceFactor = value.toReal(); break;
261     case OvershootDragDistanceFactor:   d->overshootDragDistanceFactor = qBound(qreal(0), value.toReal(), qreal(1)); break;
262     case OvershootScrollDistanceFactor: d->overshootScrollDistanceFactor = qBound(qreal(0), value.toReal(), qreal(1)); break;
263     case OvershootScrollTime:           d->overshootScrollTime = value.toReal(); break;
264     case HorizontalOvershootPolicy:     d->hOvershootPolicy = qvariant_cast<QScrollerProperties::OvershootPolicy>(value); break;
265     case VerticalOvershootPolicy:       d->vOvershootPolicy = qvariant_cast<QScrollerProperties::OvershootPolicy>(value); break;
266     case FrameRate:                     d->frameRate = qvariant_cast<QScrollerProperties::FrameRates>(value); break;
267     case ScrollMetricCount:             break;
268     }
269 }
270 
271 /*!
272     \enum QScrollerProperties::FrameRates
273 
274     This enum describes the available frame rates used while dragging or scrolling.
275 
276     \value Fps60 60 frames per second
277     \value Fps30 30 frames per second
278     \value Fps20 20 frames per second
279     \value Standard the default value is 60 frames per second (which corresponds to QAbstractAnimation).
280 */
281 
282 /*!
283     \enum QScrollerProperties::OvershootPolicy
284 
285     This enum describes the various modes of overshooting.
286 
287     \value OvershootWhenScrollable Overshooting is possible when the content is scrollable. This is the
288                                    default.
289 
290     \value OvershootAlwaysOff Overshooting is never enabled, even when the content is scrollable.
291 
292     \value OvershootAlwaysOn Overshooting is always enabled, even when the content is not
293                              scrollable.
294 */
295 
296 /*!
297     \enum QScrollerProperties::ScrollMetric
298 
299     This enum contains the different scroll metric types. When not indicated otherwise the
300     setScrollMetric function expects a QVariant of type qreal.
301 
302     See the QScroller documentation for further details of the concepts behind the different
303     values.
304 
305     \value MousePressEventDelay This is the time a mouse press event is delayed when starting
306     a flick gesture in \c{[s]}. If the gesture is triggered within that time, no mouse press or
307     release is sent to the scrolled object. If it triggers after that delay the delayed
308     mouse press plus a faked release event at global position \c{QPoint(-QWIDGETSIZE_MAX,
309     -QWIDGETSIZE_MAX)} is sent. If the gesture is canceled, then both the delayed mouse
310     press plus the real release event are delivered.
311 
312     \value DragStartDistance This is the minimum distance the touch or mouse point needs to be
313     moved before the flick gesture is triggered in \c m.
314 
315     \value DragVelocitySmoothingFactor A value that describes to which extent new drag velocities are
316     included in the final scrolling velocity.  This value should be in the range between \c 0 and
317     \c 1.  The lower the value, the more smoothing is applied to the dragging velocity.
318 
319     \value AxisLockThreshold Restricts the movement to one axis if the movement is inside an angle
320     around the axis. The threshold must be in the range \c 0 to \c 1.
321 
322     \value ScrollingCurve The QEasingCurve used when decelerating the scrolling velocity after an
323     user initiated flick. Please note that this is the easing curve for the positions, \b{not}
324     the velocity: the default is QEasingCurve::OutQuad, which results in a linear decrease in
325     velocity (1st derivative) and a constant deceleration (2nd derivative).
326 
327     \value DecelerationFactor This factor influences how long it takes the scroller to decelerate
328     to 0 velocity. The actual value depends on the chosen ScrollingCurve. For most
329     types the value should be in the range from \c 0.1 to \c 2.0
330 
331     \value MinimumVelocity The minimum velocity that is needed after ending the touch or releasing
332     the mouse to start scrolling in \c{m/s}.
333 
334     \value MaximumVelocity This is the maximum velocity that can be reached in \c{m/s}.
335 
336     \value MaximumClickThroughVelocity This is the maximum allowed scroll speed for a click-through
337     in \c{m/s}. This means that a click on a currently (slowly) scrolling object will not only stop
338     the scrolling but the click event will also be delivered to the UI control. This is
339     useful when using exponential-type scrolling curves.
340 
341     \value AcceleratingFlickMaximumTime This is the maximum time in \c seconds that a flick gesture
342     can take to be recognized as an accelerating flick. If set to zero no such gesture is
343     detected. An "accelerating flick" is a flick gesture executed on an already scrolling object.
344     In such cases the scrolling speed is multiplied by AcceleratingFlickSpeedupFactor in order to
345     accelerate it.
346 
347     \value AcceleratingFlickSpeedupFactor The current speed is multiplied by this number if an
348     accelerating flick is detected. Should be \c{>= 1}.
349 
350     \value SnapPositionRatio This is the distance that the user must drag the area beween two snap
351     points in order to snap it to the next position. \c{0.33} means that the scroll must only
352     reach one third of the distance between two snap points to snap to the next one. The ratio must
353     be between \c 0 and \c 1.
354 
355     \value SnapTime This is the time factor for the scrolling curve. A lower value means that the
356     scrolling will take longer. The scrolling distance is independet of this value.
357 
358     \value OvershootDragResistanceFactor This value is the factor between the mouse dragging and
359     the actual scroll area movement (during overshoot). The factor must be between \c 0 and \c 1.
360 
361     \value OvershootDragDistanceFactor This is the maximum distance for overshoot movements while
362     dragging. The actual overshoot distance is calculated by multiplying this value with the
363     viewport size of the scrolled object. The factor must be between \c 0 and \c 1.
364 
365     \value OvershootScrollDistanceFactor This is the maximum distance for overshoot movements while
366     scrolling. The actual overshoot distance is calculated by multiplying this value with the
367     viewport size of the scrolled object. The factor must be between \c 0 and \c 1.
368 
369     \value OvershootScrollTime This is the time in \c seconds that is used to play the
370     complete overshoot animation.
371 
372     \value HorizontalOvershootPolicy This is the horizontal overshooting policy (see OvershootPolicy).
373 
374     \value VerticalOvershootPolicy This is the horizontal overshooting policy (see OvershootPolicy).
375 
376     \value FrameRate This is the frame rate which should be used while dragging or scrolling.
377     QScroller uses a QAbstractAnimation timer internally to sync all scrolling operations to other
378     animations that might be active at the same time.  If the standard value of 60 frames per
379     second is too fast, it can be lowered with this setting,
380     while still being in-sync with QAbstractAnimation. Please note that only the values of the
381     FrameRates enum are allowed here.
382 
383     \value ScrollMetricCount This is always the last entry.
384 */
385 
386 QT_END_NAMESPACE
387