From a0b04da1d95a67d1ba431b7652026bd72d86962e Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 21 Mar 2022 14:35:22 +0300 Subject: [PATCH] Added utils for fade animated showing/hiding of widgets. --- CMakeLists.txt | 2 + ui/effects/show_animation.cpp | 110 ++++++++++++++++++++++++++++++++++ ui/effects/show_animation.h | 20 +++++++ 3 files changed, 132 insertions(+) create mode 100644 ui/effects/show_animation.cpp create mode 100644 ui/effects/show_animation.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cc6654b..fb289c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,8 @@ PRIVATE ui/effects/radial_animation.h ui/effects/ripple_animation.cpp ui/effects/ripple_animation.h + ui/effects/show_animation.cpp + ui/effects/show_animation.h ui/effects/slide_animation.cpp ui/effects/slide_animation.h ui/gl/gl_detection.cpp diff --git a/ui/effects/show_animation.cpp b/ui/effects/show_animation.cpp new file mode 100644 index 0000000..2e7a362 --- /dev/null +++ b/ui/effects/show_animation.cpp @@ -0,0 +1,110 @@ +// 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/show_animation.h" + +#include "ui/effects/animations.h" +#include "ui/rp_widget.h" +#include "styles/style_widgets.h" + +namespace Ui::Animations { +namespace { + +void AnimateWidgets(const Widgets &targets, bool show) { + enum class Finish { + Bad, + Good, + }; + struct Object { + base::unique_qptr container; + QPointer weakTarget; + }; + struct State { + rpl::event_stream destroy; + Ui::Animations::Simple animation; + std::vector objects; + }; + auto lifetime = std::make_shared(); + const auto state = lifetime->make_state(); + + const auto from = show ? 0. : 1.; + const auto to = show ? 1. : 0.; + + for (const auto &target : targets) { + state->objects.push_back({ + base::make_unique_q(target->parentWidget()), + Ui::MakeWeak(target), + }); + + const auto pixmap = Ui::GrabWidget(target); + const auto raw = state->objects.back().container.get(); + + raw->paintRequest( + ) | rpl::start_with_next([=] { + QPainter p(raw); + + p.setOpacity(state->animation.value(to)); + p.drawPixmap(QPoint(), pixmap); + }, raw->lifetime()); + + target->geometryValue( + ) | rpl::start_with_next([=](const QRect &r) { + raw->setGeometry(r); + }, raw->lifetime()); + + raw->show(); + + if (!show) { + target->hide(); + } + } + + state->destroy.events( + ) | rpl::take( + 1 + ) | rpl::start_with_next([=](Finish type) mutable { + if (type == Finish::Good && show) { + for (const auto &object : state->objects) { + if (object.weakTarget) { + object.weakTarget->show(); + } + } + } + if (lifetime) { + base::take(lifetime)->destroy(); + } + }, *lifetime); + + state->animation.start( + [=](auto value) { + for (const auto &object : state->objects) { + object.container->update(); + + if (!object.weakTarget && show) { + state->destroy.fire(Finish::Bad); + return; + } + } + if (value == to) { + state->destroy.fire(Finish::Good); + } + }, + from, + to, + st::defaultToggle.duration); +} + +} // namespace + +void ShowWidgets(const Widgets &targets) { + AnimateWidgets(targets, true); +} + +void HideWidgets(const Widgets &targets) { + AnimateWidgets(targets, false); +} + +} // namespace Ui::Animations diff --git a/ui/effects/show_animation.h b/ui/effects/show_animation.h new file mode 100644 index 0000000..d75735d --- /dev/null +++ b/ui/effects/show_animation.h @@ -0,0 +1,20 @@ +// 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 + +namespace Ui { +class RpWidget; +} // namespace Ui + +namespace Ui::Animations { + +using Widgets = std::vector>; + +void ShowWidgets(const Widgets &targets); +void HideWidgets(const Widgets &targets); + +} // namespace Ui::Animations