Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickboundaryrule.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <qqmlcontext.h>
7#include <qqmlinfo.h>
8#include <private/qqmlproperty_p.h>
9#include <private/qqmlengine_p.h>
10#include <private/qobject_p.h>
11#include <private/qquickanimation_p_p.h>
12#include <QtCore/qloggingcategory.h>
13
15
16Q_LOGGING_CATEGORY(lcBR, "qt.quick.boundaryrule")
17
20{
21 Q_DECLARE_PUBLIC(QQuickBoundaryRule)
22public:
24
27 QQuickBoundaryReturnJob *returnAnimationJob = nullptr;
28 // read-only properties, updated on each write()
29 qreal targetValue = 0; // after easing was applied
30 qreal peakOvershoot = 0;
31 qreal currentOvershoot = 0;
32 // settable properties
33 qreal minimum = 0;
34 qreal maximum = 0;
35 qreal minimumOvershoot = 0;
36 qreal maximumOvershoot = 0;
37 qreal overshootScale = 0.5;
38 int returnDuration = 100;
40 bool enabled = true;
41 bool completed = false;
42
43 qreal easedOvershoot(qreal overshootingValue);
44 void resetOvershoot();
45 void onAnimationEnded();
46};
47
49{
50public:
56
57 int duration() const override { return boundaryRule->returnDuration; }
58
59 void updateCurrentTime(int) override;
60
62 QAbstractAnimationJob::State oldState) override;
63
65 qreal fromValue; // snapshot of initial value from which we're returning
66 qreal toValue; // target property value to which we're returning
67};
68
70{
71 // The easing property tells how to behave when the property is being
72 // externally manipulated beyond the bounds. During returnToBounds()
73 // we run it in reverse, by reversing time.
74 qreal progress = (duration() - t) / qreal(duration());
75 qreal easingValue = boundaryRule->easing.valueForProgress(progress);
76 qreal delta = qAbs(fromValue - toValue) * easingValue;
77 qreal value = (fromValue > toValue ? toValue + delta : toValue - delta);
78 qCDebug(lcBR) << t << "ms" << qRound(progress * 100) << "% easing" << easingValue << "->" << value;
81}
82
92
96
122
124{
126 // stop any running animation and
127 // prevent QQuickBoundaryReturnJob::updateState() from accessing QQuickBoundaryRulePrivate
128 delete d->returnAnimationJob;
129}
130
140{
141 Q_D(const QQuickBoundaryRule);
142 return d->enabled;
143}
144
146{
148 if (d->enabled == enabled)
149 return;
150 d->enabled = enabled;
152}
153
164{
165 Q_D(const QQuickBoundaryRule);
166 return d->minimum;
167}
168
170{
172 if (qFuzzyCompare(d->minimum, minimum))
173 return;
174 d->minimum = minimum;
176}
177
190{
191 Q_D(const QQuickBoundaryRule);
192 return d->minimumOvershoot;
193}
194
196{
198 if (qFuzzyCompare(d->minimumOvershoot, minimumOvershoot))
199 return;
200 d->minimumOvershoot = minimumOvershoot;
202}
203
214{
215 Q_D(const QQuickBoundaryRule);
216 return d->maximum;
217}
218
220{
222 if (qFuzzyCompare(d->maximum, maximum))
223 return;
224 d->maximum = maximum;
226}
227
240{
241 Q_D(const QQuickBoundaryRule);
242 return d->maximumOvershoot;
243}
244
246{
248 if (qFuzzyCompare(d->maximumOvershoot, maximumOvershoot))
249 return;
250 d->maximumOvershoot = maximumOvershoot;
252}
253
272{
273 Q_D(const QQuickBoundaryRule);
274 return d->overshootScale;
275}
276
278{
280 if (qFuzzyCompare(d->overshootScale, overshootScale))
281 return;
282 d->overshootScale = overshootScale;
284}
285
297{
298 Q_D(const QQuickBoundaryRule);
299 return d->currentOvershoot;
300}
301
315{
316 Q_D(const QQuickBoundaryRule);
317 return d->peakOvershoot;
318}
319
332{
333 Q_D(const QQuickBoundaryRule);
334 return d->overshootFilter;
335}
336
338{
340 if (d->overshootFilter == overshootFilter)
341 return;
342 d->overshootFilter = overshootFilter;
344}
345
359{
361 if (d->returnAnimationJob) {
362 qCDebug(lcBR) << "animation already in progress";
363 return true;
364 }
365 if (currentOvershoot() > 0) {
366 if (d->returnDuration > 0)
367 d->returnAnimationJob = new QQuickBoundaryReturnJob(d, maximum());
368 else
369 write(maximum());
370 } else if (currentOvershoot() < 0) {
371 if (d->returnDuration > 0)
372 d->returnAnimationJob = new QQuickBoundaryReturnJob(d, minimum());
373 else
374 write(minimum());
375 } else {
376 return false;
377 }
378 if (d->returnAnimationJob) {
379 qCDebug(lcBR) << d->property.name() << "on" << d->property.object()
380 << ": animating from" << d->returnAnimationJob->fromValue << "to" << d->returnAnimationJob->toValue;
381 d->returnAnimationJob->start();
382 } else {
383 d->resetOvershoot();
384 qCDebug(lcBR) << d->property.name() << "on" << d->property.object() << ": returned to" << d->property.read();
386 }
387 return true;
388}
389
411{
412 Q_D(const QQuickBoundaryRule);
413 return d->easing;
414}
415
417{
419 if (d->easing == easing)
420 return;
421 d->easing = easing;
423}
424
436{
437 Q_D(const QQuickBoundaryRule);
438 return d->returnDuration;
439}
440
442{
444 if (d->returnDuration == duration)
445 return;
446 d->returnDuration = duration;
448}
449
454
456{
458 d->completed = true;
459}
460
462{
463 bool conversionOk = false;
464 qreal rValue = value.toReal(&conversionOk);
465 if (!conversionOk) {
466 qWarning() << "BoundaryRule doesn't work with non-numeric values:" << value;
467 return;
468 }
470 bool bypass = !d->enabled || !d->completed || QQmlEnginePrivate::designerMode();
471 if (bypass) {
474 return;
475 }
476
477 d->targetValue = d->easedOvershoot(rValue);
478 QQmlPropertyPrivate::write(d->property, d->targetValue,
480}
481
483{
485 d->property = property;
486}
487
495{
496 qreal ret = value;
498 if (value > maximum) {
499 qreal overshootWas = currentOvershoot;
501 if (!qFuzzyCompare(overshootWas, currentOvershoot))
502 emit q->currentOvershootChanged();
503 overshootWas = peakOvershoot;
505 if (!qFuzzyCompare(overshootWas, peakOvershoot))
506 emit q->peakOvershootChanged();
510 qCDebug(lcBR).nospace() << value << " overshoots maximum " << maximum << " by "
511 << currentOvershoot << " (peak " << peakOvershoot << "): eased to " << ret;
512 } else if (value < minimum) {
513 qreal overshootWas = currentOvershoot;
515 if (!qFuzzyCompare(overshootWas, currentOvershoot))
516 emit q->currentOvershootChanged();
517 overshootWas = peakOvershoot;
519 if (!qFuzzyCompare(overshootWas, peakOvershoot))
520 emit q->peakOvershootChanged();
524 qCDebug(lcBR).nospace() << value << " overshoots minimum " << minimum << " by "
525 << currentOvershoot << " (peak " << peakOvershoot << "): eased to " << ret;
526 } else {
528 }
529 return ret;
530}
531
538{
540 if (!qFuzzyCompare(peakOvershoot, 0)) {
541 peakOvershoot = 0;
542 emit q->peakOvershootChanged();
543 }
546 emit q->currentOvershootChanged();
547 }
548}
549
551{
553 delete returnAnimationJob;
554 returnAnimationJob = nullptr;
555 emit q->returnedToBounds();
556}
557
559
560#include "moc_qquickboundaryrule_p.cpp"
\inmodule QtCore
qreal valueForProgress(qreal progress) const
Return the effective progress for the easing curve at progress.
\inmodule QtCore
Definition qobject.h:103
static bool designerMode()
static bool write(QObject *, const QQmlPropertyData &, const QVariant &, const QQmlRefPointer< QQmlContextData > &, QQmlPropertyData::WriteFlags flags={})
The QQmlPropertyValueInterceptor class is inherited by property interceptors such as Behavior.
The QQmlProperty class abstracts accessing properties on objects created from QML.
void updateCurrentTime(int) override
int duration() const override
QQuickBoundaryReturnJob(QQuickBoundaryRulePrivate *br, qreal to)
void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override
QQuickBoundaryRulePrivate * boundaryRule
qreal easedOvershoot(qreal overshootingValue)
QQuickBoundaryReturnJob * returnAnimationJob
QQuickBoundaryRule::OvershootFilter overshootFilter
void setTarget(const QQmlProperty &) override
Set the target property for the value interceptor.
void setMinimum(qreal minimum)
void overshootFilterChanged()
void classBegin() override
Invoked after class creation, but before any properties have been set.
OvershootFilter overshootFilter
void setMinimumOvershoot(qreal minimum)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void maximumOvershootChanged()
void setOvershootScale(qreal scale)
void returnDurationChanged()
void setEnabled(bool enabled)
void setMaximumOvershoot(qreal maximum)
QQuickBoundaryRule(QObject *parent=nullptr)
Defines a restriction on the range of values that can be set on a numeric property.
void write(const QVariant &value) override
This method will be called when a new value is assigned to the property being intercepted.
void setEasing(const QEasingCurve &easing)
void overshootScaleChanged()
void setMaximum(qreal maximum)
Q_INVOKABLE bool returnToBounds()
\qmlmethod bool Qt.labs.animation::BoundaryRule::returnToBounds
void setReturnDuration(int duration)
void setOvershootFilter(OvershootFilter overshootFilter)
void minimumOvershootChanged()
\inmodule QtCore
Definition qvariant.h:65
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
return ret
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
const char property[13]
Definition qwizard.cpp:101
QEasingCurve easing(QEasingCurve::InOutQuad)
[typedef]