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
47QT_BEGIN_NAMESPACE
48
49static QScrollerPropertiesPrivate *userDefaults = nullptr;
50static QScrollerPropertiesPrivate *systemDefaults = nullptr;
51
52QScrollerPropertiesPrivate *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*/
103QScrollerProperties::QScrollerProperties()
104 : d(QScrollerPropertiesPrivate::defaults())
105{
106}
107
108/*!
109 Constructs a copy of \a sp.
110*/
111QScrollerProperties::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*/
119QScrollerProperties &QScrollerProperties::operator=(const QScrollerProperties &sp)
120{
121 *d.data() = *sp.d.data();
122 return *this;
123}
124
125/*!
126 Destroys the scroller properties.
127*/
128QScrollerProperties::~QScrollerProperties()
129{
130}
131
132/*!
133 Returns \c true if these scroller properties are equal to \a sp; otherwise returns \c false.
134*/
135bool 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*/
143bool QScrollerProperties::operator!=(const QScrollerProperties &sp) const
144{
145 return !(*d.data() == *sp.d.data());
146}
147
148bool 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*/
186void 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*/
200void 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*/
211QVariant 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*/
244void 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
386QT_END_NAMESPACE
387