Implement BoxShow as a wrapper around long-living *Show.

This commit is contained in:
John Preston 2023-03-10 18:40:49 +04:00
parent f3744c4ba3
commit 849a840503
10 changed files with 145 additions and 25 deletions

View file

@ -317,37 +317,65 @@ void BoxContent::paintEvent(QPaintEvent *e) {
}
}
BoxShow::BoxShow(not_null<Ui::BoxContent*> box)
: Show()
, _weak(Ui::MakeWeak(box.get())) {
BoxShow::BoxShow(not_null<BoxContent*> box)
: BoxShow(MakeWeak(box.get()), nullptr) {
}
BoxShow::BoxShow(const BoxShow &other)
: BoxShow(other._weak, other._wrapped) {
}
BoxShow::BoxShow(QPointer<BoxContent> weak, ShowPtr wrapped)
: _weak(weak)
, _wrapped(std::move(wrapped)) {
if (!resolve()) {
if (const auto box = _weak.data()) {
box->boxClosing(
) | rpl::start_with_next([=] {
resolve();
_lifetime.destroy();
}, _lifetime);
}
}
}
BoxShow::~BoxShow() = default;
bool BoxShow::resolve() const {
if (_wrapped) {
return true;
} else if (const auto strong = _weak.data()) {
if (strong->hasDelegate()) {
_wrapped = strong->getDelegate()->showFactory()();
return true;
}
}
return false;
}
void BoxShow::showBox(
object_ptr<BoxContent> content,
LayerOptions options) const {
if (const auto strong = _weak.data()) {
strong->getDelegate()->show(std::move(content), options);
if (resolve()) {
_wrapped->showBox(std::move(content), options);
}
}
void BoxShow::hideLayer() const {
if (const auto strong = _weak.data()) {
strong->getDelegate()->hideLayer();
if (resolve()) {
_wrapped->hideLayer();
}
}
not_null<QWidget*> BoxShow::toastParent() const {
if (!_toastParent) {
Assert(_weak != nullptr);
_toastParent = Ui::MakeWeak(_weak->window()); // =(
if (resolve()) {
return _wrapped->toastParent();
}
return _toastParent.data();
Unexpected("Stale BoxShow::toastParent call.");
}
bool BoxShow::valid() const {
return _weak;
return resolve() && _wrapped->valid();
}
BoxShow::operator bool() const {

View file

@ -95,6 +95,7 @@ public:
return result;
}
virtual ShowFactory showFactory() = 0;
virtual QPointer<QWidget> outerContainer() = 0;
};
@ -190,6 +191,9 @@ public:
prepare();
finishPrepare();
}
[[nodiscard]] bool hasDelegate() const {
return _delegate != nullptr;
}
[[nodiscard]] not_null<BoxContentDelegate*> getDelegate() const {
return _delegate;
}
@ -352,6 +356,7 @@ private:
class BoxShow : public Show {
public:
explicit BoxShow(not_null<Ui::BoxContent*> box);
BoxShow(const BoxShow &other);
~BoxShow();
void showBox(
object_ptr<BoxContent> content,
@ -360,9 +365,16 @@ public:
[[nodiscard]] not_null<QWidget*> toastParent() const override;
[[nodiscard]] bool valid() const override;
operator bool() const override;
private:
mutable QPointer<QWidget> _toastParent;
BoxShow(QPointer<BoxContent> weak, ShowPtr wrapped);
bool resolve() const;
const QPointer<Ui::BoxContent> _weak;
mutable std::shared_ptr<Show> _wrapped;
rpl::lifetime _lifetime;
};
} // namespace Ui

View file

@ -238,6 +238,10 @@ void BoxLayerWidget::updateButtonsPositions() {
}
}
ShowFactory BoxLayerWidget::showFactory() {
return _layer->showFactory();
}
QPointer<QWidget> BoxLayerWidget::outerContainer() {
return parentWidget();
}

View file

@ -58,6 +58,7 @@ public:
void addTopButton(object_ptr<AbstractButton> button) override;
void showLoading(bool show) override;
void updateButtonsPositions() override;
ShowFactory showFactory() override;
QPointer<QWidget> outerContainer() override;
void setDimensions(

View file

@ -6,7 +6,67 @@
//
#include "ui/layers/layer_manager.h"
#include "ui/layers/show.h"
namespace Ui {
namespace {
class ManagerShow final : public Show {
public:
explicit ManagerShow(not_null<LayerManager*> manager);
~ManagerShow();
void showBox(
object_ptr<Ui::BoxContent> content,
Ui::LayerOptions options = Ui::LayerOption::KeepOther) const override;
void hideLayer() const override;
[[nodiscard]] not_null<QWidget*> toastParent() const override;
[[nodiscard]] bool valid() const override;
operator bool() const override;
private:
const base::weak_ptr<LayerManager> _manager;
};
ManagerShow::ManagerShow(not_null<LayerManager*> manager)
: _manager(manager.get()) {
}
ManagerShow::~ManagerShow() = default;
void ManagerShow::showBox(
object_ptr<Ui::BoxContent> content,
Ui::LayerOptions options) const {
if (const auto manager = _manager.get()) {
manager->showBox(std::move(content), options, anim::type::normal);
}
}
void ManagerShow::hideLayer() const {
if (const auto manager = _manager.get()) {
manager->showBox(
object_ptr<Ui::BoxContent>{ nullptr },
Ui::LayerOption::CloseOther,
anim::type::normal);
}
}
not_null<QWidget*> ManagerShow::toastParent() const {
const auto manager = _manager.get();
Ensures(manager != nullptr);
return manager->toastParent();
}
bool ManagerShow::valid() const {
return (_manager.get() != nullptr);
}
ManagerShow::operator bool() const {
return valid();
}
} // namespace
LayerManager::LayerManager(not_null<RpWidget*> widget) : _widget(widget) {
}
@ -67,7 +127,9 @@ void LayerManager::ensureLayerCreated() {
if (_layer) {
return;
}
_layer.emplace(_widget);
_layer.emplace(_widget, crl::guard(this, [=] {
return std::make_shared<ManagerShow>(this);
}));
_layer->setHideByBackgroundClick(_hideByBackgroundClick);
_layer->setStyleOverrides(_boxSt, _layerSt);

View file

@ -6,6 +6,7 @@
//
#pragma once
#include "base/weak_ptr.h"
#include "ui/layers/layer_widget.h"
#include <QtCore/QMargins>
@ -19,7 +20,7 @@ namespace Ui {
class BoxContent;
class RpWidget;
class LayerManager final {
class LayerManager final : public base::has_weak_ptr {
public:
explicit LayerManager(not_null<RpWidget*> widget);
@ -36,7 +37,10 @@ public:
void raise();
bool setFocus();
const LayerWidget *topShownLayer() const;
[[nodiscard]] not_null<Ui::RpWidget*> toastParent() const {
return _widget;
}
[[nodiscard]] const LayerWidget *topShownLayer() const;
private:
void ensureLayerCreated();

View file

@ -324,9 +324,10 @@ void LayerStackWidget::BackgroundWidget::animationCallback() {
checkIfDone();
}
LayerStackWidget::LayerStackWidget(QWidget *parent)
LayerStackWidget::LayerStackWidget(QWidget *parent, ShowFactory showFactory)
: RpWidget(parent)
, _background(this) {
, _background(this)
, _showFactory(std::move(showFactory)) {
setGeometry(parentWidget()->rect());
hide();
_background->setDoneCallback([this] { animationDone(); });

View file

@ -32,7 +32,11 @@ enum class LayerOption {
using LayerOptions = base::flags<LayerOption>;
inline constexpr auto is_flag_type(LayerOption) { return true; };
class LayerWidget : public Ui::RpWidget {
class Show;
using ShowPtr = std::shared_ptr<Show>;
using ShowFactory = Fn<ShowPtr()>;
class LayerWidget : public RpWidget {
public:
using RpWidget::RpWidget;
@ -91,9 +95,9 @@ private:
};
class LayerStackWidget : public Ui::RpWidget {
class LayerStackWidget : public RpWidget {
public:
LayerStackWidget(QWidget *parent);
LayerStackWidget(QWidget *parent, ShowFactory showFactory);
void finishAnimating();
rpl::producer<> hideFinishEvents() const;
@ -107,6 +111,9 @@ public:
[[nodiscard]] const style::Box *boxStyleOverride() const {
return _boxSt;
}
[[nodiscard]] ShowFactory showFactory() const {
return _showFactory;
}
void showBox(
object_ptr<BoxContent> box,
@ -222,6 +229,8 @@ private:
class BackgroundWidget;
object_ptr<BackgroundWidget> _background;
ShowFactory _showFactory;
const style::Box *_boxSt = nullptr;
const style::Box *_layerSt = nullptr;
bool _hideByBackgroundClick = true;

View file

@ -26,7 +26,4 @@ public:
inline Show::~Show() = default;
using ShowPtr = std::shared_ptr<Show>;
} // namespace Ui

View file

@ -425,7 +425,9 @@ void SeparatePanel::ensureLayerCreated() {
if (_layer) {
return;
}
_layer = base::make_unique_q<Ui::LayerStackWidget>(_body);
_layer = base::make_unique_q<Ui::LayerStackWidget>(
_body,
crl::guard(this, [=] { return std::make_shared<PanelShow>(this); }));
_layer->setHideByBackgroundClick(false);
_layer->move(0, 0);
_body->sizeValue(