File indexing completed on 2024-11-10 04:56:46
0001 /* 0002 SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "effect/timeline.h" 0008 0009 namespace KWin 0010 { 0011 0012 class Q_DECL_HIDDEN TimeLine::Data : public QSharedData 0013 { 0014 public: 0015 std::chrono::milliseconds duration; 0016 Direction direction; 0017 QEasingCurve easingCurve; 0018 0019 std::chrono::milliseconds elapsed = std::chrono::milliseconds::zero(); 0020 std::optional<std::chrono::milliseconds> lastTimestamp = std::nullopt; 0021 bool done = false; 0022 RedirectMode sourceRedirectMode = RedirectMode::Relaxed; 0023 RedirectMode targetRedirectMode = RedirectMode::Strict; 0024 }; 0025 0026 TimeLine::TimeLine(std::chrono::milliseconds duration, Direction direction) 0027 : d(new Data) 0028 { 0029 Q_ASSERT(duration > std::chrono::milliseconds::zero()); 0030 d->duration = duration; 0031 d->direction = direction; 0032 } 0033 0034 TimeLine::TimeLine(const TimeLine &other) 0035 : d(other.d) 0036 { 0037 } 0038 0039 TimeLine::~TimeLine() = default; 0040 0041 qreal TimeLine::progress() const 0042 { 0043 return static_cast<qreal>(d->elapsed.count()) / d->duration.count(); 0044 } 0045 0046 qreal TimeLine::value() const 0047 { 0048 const qreal t = progress(); 0049 return d->easingCurve.valueForProgress( 0050 d->direction == Backward ? 1.0 - t : t); 0051 } 0052 0053 void TimeLine::advance(std::chrono::milliseconds timestamp) 0054 { 0055 if (d->done) { 0056 return; 0057 } 0058 0059 std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); 0060 if (d->lastTimestamp.has_value()) { 0061 delta = timestamp - d->lastTimestamp.value(); 0062 } 0063 0064 Q_ASSERT(delta >= std::chrono::milliseconds::zero()); 0065 d->lastTimestamp = timestamp; 0066 0067 d->elapsed += delta; 0068 if (d->elapsed >= d->duration) { 0069 d->elapsed = d->duration; 0070 d->done = true; 0071 d->lastTimestamp = std::nullopt; 0072 } 0073 } 0074 0075 std::chrono::milliseconds TimeLine::elapsed() const 0076 { 0077 return d->elapsed; 0078 } 0079 0080 void TimeLine::setElapsed(std::chrono::milliseconds elapsed) 0081 { 0082 Q_ASSERT(elapsed >= std::chrono::milliseconds::zero()); 0083 if (elapsed == d->elapsed) { 0084 return; 0085 } 0086 0087 reset(); 0088 0089 d->elapsed = elapsed; 0090 0091 if (d->elapsed >= d->duration) { 0092 d->elapsed = d->duration; 0093 d->done = true; 0094 d->lastTimestamp = std::nullopt; 0095 } 0096 } 0097 0098 std::chrono::milliseconds TimeLine::duration() const 0099 { 0100 return d->duration; 0101 } 0102 0103 void TimeLine::setDuration(std::chrono::milliseconds duration) 0104 { 0105 Q_ASSERT(duration > std::chrono::milliseconds::zero()); 0106 if (duration == d->duration) { 0107 return; 0108 } 0109 d->elapsed = std::chrono::milliseconds(qRound(progress() * duration.count())); 0110 d->duration = duration; 0111 if (d->elapsed == d->duration) { 0112 d->done = true; 0113 d->lastTimestamp = std::nullopt; 0114 } 0115 } 0116 0117 TimeLine::Direction TimeLine::direction() const 0118 { 0119 return d->direction; 0120 } 0121 0122 void TimeLine::setDirection(TimeLine::Direction direction) 0123 { 0124 if (d->direction == direction) { 0125 return; 0126 } 0127 0128 d->direction = direction; 0129 0130 if (d->elapsed > std::chrono::milliseconds::zero() 0131 || d->sourceRedirectMode == RedirectMode::Strict) { 0132 d->elapsed = d->duration - d->elapsed; 0133 } 0134 0135 if (d->done && d->targetRedirectMode == RedirectMode::Relaxed) { 0136 d->done = false; 0137 } 0138 0139 if (d->elapsed >= d->duration) { 0140 d->done = true; 0141 d->lastTimestamp = std::nullopt; 0142 } 0143 } 0144 0145 void TimeLine::toggleDirection() 0146 { 0147 setDirection(d->direction == Forward ? Backward : Forward); 0148 } 0149 0150 QEasingCurve TimeLine::easingCurve() const 0151 { 0152 return d->easingCurve; 0153 } 0154 0155 void TimeLine::setEasingCurve(const QEasingCurve &easingCurve) 0156 { 0157 d->easingCurve = easingCurve; 0158 } 0159 0160 void TimeLine::setEasingCurve(QEasingCurve::Type type) 0161 { 0162 d->easingCurve.setType(type); 0163 } 0164 0165 bool TimeLine::running() const 0166 { 0167 return d->elapsed != std::chrono::milliseconds::zero() 0168 && d->elapsed != d->duration; 0169 } 0170 0171 bool TimeLine::done() const 0172 { 0173 return d->done; 0174 } 0175 0176 void TimeLine::reset() 0177 { 0178 d->lastTimestamp = std::nullopt; 0179 d->elapsed = std::chrono::milliseconds::zero(); 0180 d->done = false; 0181 } 0182 0183 TimeLine::RedirectMode TimeLine::sourceRedirectMode() const 0184 { 0185 return d->sourceRedirectMode; 0186 } 0187 0188 void TimeLine::setSourceRedirectMode(RedirectMode mode) 0189 { 0190 d->sourceRedirectMode = mode; 0191 } 0192 0193 TimeLine::RedirectMode TimeLine::targetRedirectMode() const 0194 { 0195 return d->targetRedirectMode; 0196 } 0197 0198 void TimeLine::setTargetRedirectMode(RedirectMode mode) 0199 { 0200 d->targetRedirectMode = mode; 0201 } 0202 0203 TimeLine &TimeLine::operator=(const TimeLine &other) 0204 { 0205 d = other.d; 0206 return *this; 0207 } 0208 0209 } // namespace KWin