From b80dd9917278f1fec17ae9d29ab6f62219491555 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 7 Mar 2017 12:46:01 +0300 Subject: [PATCH] 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. --- .../ui/effects/widget_fade_wrap.cpp | 47 ++++++++++++++++--- .../SourceFiles/ui/effects/widget_fade_wrap.h | 32 +++++++++++-- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.cpp b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.cpp index 40290f0e4..3eca54468 100644 --- a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.cpp +++ b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.cpp @@ -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::WidgetFadeWrap(QWidget *parent , object_ptr entity , int duration -, base::lambda updateCallback) : TWidget(parent) +, base::lambda 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(); }); diff --git a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h index 1ab6e3a92..107e95249 100644 --- a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h +++ b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h @@ -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 entity , int duration = st::widgetFadeDuration - , base::lambda updateCallback = base::lambda()); + , base::lambda updateCallback = base::lambda() + , bool scaled = false); void showAnimated() { _animation.fadeIn(_duration); @@ -140,10 +145,12 @@ public: WidgetFadeWrap(QWidget *parent , object_ptr entity , int duration = st::widgetFadeDuration - , base::lambda updateCallback = base::lambda()) : WidgetFadeWrap(parent + , base::lambda updateCallback = base::lambda() + , bool scaled = false) : WidgetFadeWrap(parent , std::move(entity) , duration - , std::move(updateCallback)) { + , std::move(updateCallback) + , scaled) { } Widget *entity() { return static_cast(WidgetFadeWrap::entity()); @@ -154,4 +161,19 @@ public: }; +template +class WidgetScaledFadeWrap : public WidgetFadeWrap { +public: + WidgetScaledFadeWrap(QWidget *parent + , object_ptr entity + , int duration = st::widgetFadeDuration + , base::lambda updateCallback = base::lambda()) : WidgetFadeWrap(parent + , std::move(entity) + , duration + , std::move(updateCallback) + , true) { + } + +}; + } // namespace Ui