Ui::FadeAnimation now supports scaling.

Ui::WidgetScaledFadeWrap<> wrapper added for fading widgets out and
fading them in with a scale effect similar to Ui::SendButton.
This commit is contained in:
John Preston 2017-03-07 12:46:01 +03:00
parent 6456a83a22
commit b80dd99172
2 changed files with 68 additions and 11 deletions

View File

@ -21,8 +21,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/effects/widget_fade_wrap.h"
namespace Ui {
namespace {
FadeAnimation::FadeAnimation(TWidget *widget) : _widget(widget) {
constexpr int kWideScale = 5;
} // namespace
FadeAnimation::FadeAnimation(TWidget *widget, bool scaled)
: _widget(widget)
, _scaled(scaled) {
}
bool FadeAnimation::paint(Painter &p) {
@ -30,17 +37,44 @@ bool FadeAnimation::paint(Painter &p) {
auto opacity = _animation.current(getms(), _visible ? 1. : 0.);
p.setOpacity(opacity);
p.drawPixmap(0, 0, _cache);
if (_scaled) {
PainterHighQualityEnabler hq(p);
auto targetRect = QRect((1 - kWideScale) / 2 * _size.width(), (1 - kWideScale) / 2 * _size.height(), kWideScale * _size.width(), kWideScale * _size.height());
auto scale = opacity;
auto shownWidth = anim::interpolate((1 - kWideScale) / 2 * _size.width(), 0, scale);
auto shownHeight = anim::interpolate((1 - kWideScale) / 2 * _size.height(), 0, scale);
p.drawPixmap(targetRect.marginsAdded(QMargins(shownWidth, shownHeight, shownWidth, shownHeight)), _cache);
} else {
p.drawPixmap(0, 0, _cache);
}
return true;
}
void FadeAnimation::refreshCache() {
if (!_cache.isNull()) {
_cache = QPixmap();
_cache = myGrab(_widget);
_cache = grabContent();
}
}
QPixmap FadeAnimation::grabContent() {
myEnsureResized(_widget);
_size = _widget->size();
auto widgetContent = myGrab(_widget);
if (!_scaled) {
return widgetContent;
}
auto result = QImage(kWideScale * _size * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
result.setDevicePixelRatio(cRetinaFactor());
result.fill(Qt::transparent);
{
Painter p(&result);
p.drawPixmap((kWideScale - 1) / 2 * _size.width(), (kWideScale - 1) / 2 * _size.height(), widgetContent);
}
return App::pixmapFromImageInPlace(std::move(result));
}
void FadeAnimation::setFinishedCallback(FinishedCallback &&callback) {
_finishedCallback = std::move(callback);
}
@ -93,7 +127,7 @@ void FadeAnimation::fadeOut(int duration) {
void FadeAnimation::startAnimation(int duration) {
if (_cache.isNull()) {
_widget->showChildren();
_cache = myGrab(_widget);
_cache = grabContent();
_widget->hideChildren();
}
auto from = _visible ? 0. : 1.;
@ -119,11 +153,12 @@ void FadeAnimation::updateCallback() {
WidgetFadeWrap<TWidget>::WidgetFadeWrap(QWidget *parent
, object_ptr<TWidget> entity
, int duration
, base::lambda<void()> updateCallback) : TWidget(parent)
, base::lambda<void()> updateCallback
, bool scaled) : TWidget(parent)
, _entity(std::move(entity))
, _duration(duration)
, _updateCallback(std::move(updateCallback))
, _animation(this) {
, _animation(this, scaled) {
_animation.show();
if (_updateCallback) {
_animation.setFinishedCallback([this] { _updateCallback(); });

View File

@ -28,7 +28,7 @@ namespace Ui {
class FadeAnimation {
public:
FadeAnimation(TWidget *widget);
FadeAnimation(TWidget *widget, bool scaled = false);
bool paint(Painter &p);
void refreshCache();
@ -58,9 +58,13 @@ private:
void stopAnimation();
void updateCallback();
QPixmap grabContent();
TWidget *_widget = nullptr;
bool _scaled = false;
TWidget *_widget;
Animation _animation;
QSize _size;
QPixmap _cache;
bool _visible = false;
@ -78,7 +82,8 @@ public:
WidgetFadeWrap(QWidget *parent
, object_ptr<TWidget> entity
, int duration = st::widgetFadeDuration
, base::lambda<void()> updateCallback = base::lambda<void()>());
, base::lambda<void()> updateCallback = base::lambda<void()>()
, bool scaled = false);
void showAnimated() {
_animation.fadeIn(_duration);
@ -140,10 +145,12 @@ public:
WidgetFadeWrap(QWidget *parent
, object_ptr<Widget> entity
, int duration = st::widgetFadeDuration
, base::lambda<void()> updateCallback = base::lambda<void()>()) : WidgetFadeWrap<TWidget>(parent
, base::lambda<void()> updateCallback = base::lambda<void()>()
, bool scaled = false) : WidgetFadeWrap<TWidget>(parent
, std::move(entity)
, duration
, std::move(updateCallback)) {
, std::move(updateCallback)
, scaled) {
}
Widget *entity() {
return static_cast<Widget*>(WidgetFadeWrap<TWidget>::entity());
@ -154,4 +161,19 @@ public:
};
template <typename Widget>
class WidgetScaledFadeWrap : public WidgetFadeWrap<Widget> {
public:
WidgetScaledFadeWrap(QWidget *parent
, object_ptr<Widget> entity
, int duration = st::widgetFadeDuration
, base::lambda<void()> updateCallback = base::lambda<void()>()) : WidgetFadeWrap<Widget>(parent
, std::move(entity)
, duration
, std::move(updateCallback)
, true) {
}
};
} // namespace Ui