genode/repos/gems/src/app/menu_view/animated_color.h

118 lines
2.4 KiB
C++

/*
* \brief Helper for implementing the fading of colors
* \author Norman Feske
* \date 2020-02-19
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ANIMATED_COLOR_H_
#define _ANIMATED_COLOR_H_
/* demo includes */
#include <util/lazy_value.h>
#include <util/color.h>
#include <gems/animator.h>
namespace Genode { class Animated_color; }
class Genode::Animated_color : private Animator::Item, Noncopyable
{
public:
struct Steps { unsigned value; };
private:
Color _color { };
using Lazy_value = ::Lazy_value<int>;
struct Animated_channel
{
bool _initial = true;
Lazy_value _value { };
Steps _remaining { 0 };
void animate()
{
_value.animate();
if (_remaining.value > 1)
_remaining.value--;
}
bool animated() const { return _value != _value.dst(); }
void fade_to(int value, Steps steps)
{
if (_initial) {
_value = Lazy_value(value << 10);
_initial = false;
} else {
/* retarget animation while already in progress */
if (animated())
steps.value = max(_remaining.value, 1U);
_value.dst(value << 10, steps.value);
_remaining = steps;
}
}
int value() const { return _value >> 10; }
};
Animated_channel _r { }, _g { }, _b { }, _a { };
public:
Animated_color(Animator &animator) : Animator::Item(animator) { }
/**
* Animator::Item interface
*/
void animate() override
{
_r.animate(); _g.animate(); _b.animate(); _a.animate();
_color = Color(_r.value(), _g.value(), _b.value(), _a.value());
/* schedule / de-schedule animation */
Animator::Item::animated(_r.animated() || _g.animated() ||
_b.animated() || _a.animated());
}
/**
* Assign new target color
*
* The first assignment assigns the color directly without animation.
* All subsequent assignments result in an animated transition to the
* target color.
*/
void fade_to(Color color, Steps steps)
{
_r.fade_to(color.r, steps);
_g.fade_to(color.g, steps);
_b.fade_to(color.b, steps);
_a.fade_to(color.a, steps);
animate();
}
bool animated() const { return Animator::Item::animated(); }
Color color() const { return _color; }
};
#endif /* _ANIMATED_COLOR_H_ */