Add Ui::PathShiftGradient effect.
This commit is contained in:
parent
3b3413e618
commit
baf4d80867
3 changed files with 241 additions and 0 deletions
|
|
@ -51,6 +51,8 @@ PRIVATE
|
|||
ui/effects/numbers_animation.h
|
||||
ui/effects/panel_animation.cpp
|
||||
ui/effects/panel_animation.h
|
||||
ui/effects/path_shift_gradient.cpp
|
||||
ui/effects/path_shift_gradient.h
|
||||
ui/effects/radial_animation.cpp
|
||||
ui/effects/radial_animation.h
|
||||
ui/effects/ripple_animation.cpp
|
||||
|
|
|
|||
175
ui/effects/path_shift_gradient.cpp
Normal file
175
ui/effects/path_shift_gradient.cpp
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#include "ui/effects/path_shift_gradient.h"
|
||||
|
||||
#include "base/call_delayed.h"
|
||||
#include "ui/effects/animations.h"
|
||||
|
||||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
constexpr auto kSlideDuration = crl::time(1000);
|
||||
constexpr auto kWaitDuration = crl::time(1000);
|
||||
constexpr auto kFullDuration = kSlideDuration + kWaitDuration;
|
||||
|
||||
} // namespace
|
||||
|
||||
struct PathShiftGradient::AnimationData {
|
||||
Ui::Animations::Simple animation;
|
||||
base::flat_set<not_null<PathShiftGradient*>> active;
|
||||
bool scheduled = false;
|
||||
};
|
||||
|
||||
std::weak_ptr<PathShiftGradient::AnimationData> PathShiftGradient::Animation;
|
||||
|
||||
PathShiftGradient::PathShiftGradient(
|
||||
const style::color &bg,
|
||||
const style::color &fg,
|
||||
Fn<void()> animationCallback)
|
||||
: _bg(bg)
|
||||
, _fg(fg)
|
||||
, _animationCallback(std::move(animationCallback)) {
|
||||
refreshColors();
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshColors();
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
PathShiftGradient::~PathShiftGradient() {
|
||||
if (const auto strong = _animation.get()) {
|
||||
strong->active.erase(this);
|
||||
}
|
||||
}
|
||||
|
||||
void PathShiftGradient::overrideColors(
|
||||
const style::color &bg,
|
||||
const style::color &fg) {
|
||||
_colorsOverriden = true;
|
||||
refreshColors(bg, fg);
|
||||
}
|
||||
|
||||
void PathShiftGradient::clearOverridenColors() {
|
||||
if (!_colorsOverriden) {
|
||||
return;
|
||||
}
|
||||
_colorsOverriden = false;
|
||||
refreshColors();
|
||||
}
|
||||
|
||||
void PathShiftGradient::startFrame(
|
||||
int viewportLeft,
|
||||
int viewportWidth,
|
||||
int gradientWidth) {
|
||||
_viewportLeft = viewportLeft;
|
||||
_viewportWidth = viewportWidth;
|
||||
_gradientWidth = gradientWidth;
|
||||
_geometryUpdated = false;
|
||||
}
|
||||
|
||||
void PathShiftGradient::updateGeometry() {
|
||||
if (_geometryUpdated) {
|
||||
return;
|
||||
}
|
||||
_geometryUpdated = true;
|
||||
const auto now = crl::now();
|
||||
const auto period = now % kFullDuration;
|
||||
if (period >= kSlideDuration) {
|
||||
_gradientEnabled = false;
|
||||
return;
|
||||
}
|
||||
const auto progress = period / float64(kSlideDuration);
|
||||
_gradientStart = anim::interpolate(
|
||||
_viewportLeft - _gradientWidth,
|
||||
_viewportLeft + _viewportWidth,
|
||||
progress);
|
||||
_gradientFinalStop = _gradientStart + _gradientWidth;
|
||||
_gradientEnabled = true;
|
||||
}
|
||||
|
||||
bool PathShiftGradient::paint(Fn<bool(const Background&)> painter) {
|
||||
updateGeometry();
|
||||
if (_gradientEnabled) {
|
||||
_gradient.setStart(_gradientStart, 0);
|
||||
_gradient.setFinalStop(_gradientFinalStop, 0);
|
||||
}
|
||||
const auto background = _gradientEnabled
|
||||
? Background(&_gradient)
|
||||
: _bgOverride
|
||||
? *_bgOverride
|
||||
: _bg;
|
||||
if (!painter(background)) {
|
||||
return false;
|
||||
}
|
||||
activateAnimation();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PathShiftGradient::activateAnimation() {
|
||||
if (_animationActive) {
|
||||
return;
|
||||
}
|
||||
_animationActive = true;
|
||||
if (!_animation) {
|
||||
_animation = Animation.lock();
|
||||
if (!_animation) {
|
||||
_animation = std::make_shared<AnimationData>();
|
||||
Animation = _animation;
|
||||
}
|
||||
}
|
||||
const auto raw = _animation.get();
|
||||
if (_animationCallback) {
|
||||
raw->active.emplace(this);
|
||||
}
|
||||
|
||||
const auto globalCallback = [] {
|
||||
const auto strong = Animation.lock();
|
||||
if (!strong) {
|
||||
return;
|
||||
}
|
||||
strong->scheduled = false;
|
||||
while (!strong->active.empty()) {
|
||||
const auto entry = strong->active.back();
|
||||
strong->active.erase(strong->active.end() - 1);
|
||||
entry->_animationActive = false;
|
||||
entry->_animationCallback();
|
||||
}
|
||||
};
|
||||
|
||||
const auto now = crl::now();
|
||||
const auto period = now % kFullDuration;
|
||||
if (period >= kSlideDuration) {
|
||||
const auto tillWaitFinish = kFullDuration - period;
|
||||
if (!raw->scheduled) {
|
||||
raw->scheduled = true;
|
||||
raw->animation.stop();
|
||||
base::call_delayed(tillWaitFinish, globalCallback);
|
||||
}
|
||||
} else {
|
||||
const auto tillSlideFinish = kSlideDuration - period;
|
||||
if (!raw->animation.animating()) {
|
||||
raw->animation.start(globalCallback, 0., 1., tillSlideFinish);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PathShiftGradient::refreshColors() {
|
||||
refreshColors(_bg, _fg);
|
||||
}
|
||||
|
||||
void PathShiftGradient::refreshColors(
|
||||
const style::color &bg,
|
||||
const style::color &fg) {
|
||||
_gradient.setStops({
|
||||
{ 0., bg->c },
|
||||
{ 0.5, fg->c },
|
||||
{ 1., bg->c },
|
||||
});
|
||||
_bgOverride = _colorsOverriden ? &bg : nullptr;
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
64
ui/effects/path_shift_gradient.h
Normal file
64
ui/effects/path_shift_gradient.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "ui/style/style_core_types.h"
|
||||
|
||||
#include <QtGui/QLinearGradient>
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class PathShiftGradient final {
|
||||
public:
|
||||
PathShiftGradient(
|
||||
const style::color &bg,
|
||||
const style::color &fg,
|
||||
Fn<void()> animationCallback);
|
||||
~PathShiftGradient();
|
||||
|
||||
void startFrame(
|
||||
int viewportLeft,
|
||||
int viewportWidth,
|
||||
int gradientWidth);
|
||||
|
||||
void overrideColors(const style::color &bg, const style::color &fg);
|
||||
void clearOverridenColors();
|
||||
|
||||
using Background = std::variant<QLinearGradient*, style::color>;
|
||||
bool paint(Fn<bool(const Background&)> painter);
|
||||
|
||||
private:
|
||||
struct AnimationData;
|
||||
|
||||
void refreshColors();
|
||||
void refreshColors(const style::color &bg, const style::color &fg);
|
||||
void updateGeometry();
|
||||
void activateAnimation();
|
||||
|
||||
static std::weak_ptr<AnimationData> Animation;
|
||||
|
||||
const style::color &_bg;
|
||||
const style::color &_fg;
|
||||
const style::color *_bgOverride = nullptr;
|
||||
QLinearGradient _gradient;
|
||||
std::shared_ptr<AnimationData> _animation;
|
||||
const Fn<void()> _animationCallback;
|
||||
int _viewportLeft = 0;
|
||||
int _viewportWidth = 0;
|
||||
int _gradientWidth = 0;
|
||||
int _gradientStart = 0;
|
||||
int _gradientFinalStop = 0;
|
||||
bool _gradientEnabled = false;
|
||||
bool _geometryUpdated = false;
|
||||
bool _animationActive = false;
|
||||
bool _colorsOverriden = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Ui
|
||||
Loading…
Add table
Reference in a new issue