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) BoxShow::BoxShow(not_null<BoxContent*> box)
: Show() : BoxShow(MakeWeak(box.get()), nullptr) {
, _weak(Ui::MakeWeak(box.get())) { }
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; 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( void BoxShow::showBox(
object_ptr<BoxContent> content, object_ptr<BoxContent> content,
LayerOptions options) const { LayerOptions options) const {
if (const auto strong = _weak.data()) { if (resolve()) {
strong->getDelegate()->show(std::move(content), options); _wrapped->showBox(std::move(content), options);
} }
} }
void BoxShow::hideLayer() const { void BoxShow::hideLayer() const {
if (const auto strong = _weak.data()) { if (resolve()) {
strong->getDelegate()->hideLayer(); _wrapped->hideLayer();
} }
} }
not_null<QWidget*> BoxShow::toastParent() const { not_null<QWidget*> BoxShow::toastParent() const {
if (!_toastParent) { if (resolve()) {
Assert(_weak != nullptr); return _wrapped->toastParent();
_toastParent = Ui::MakeWeak(_weak->window()); // =(
} }
return _toastParent.data(); Unexpected("Stale BoxShow::toastParent call.");
} }
bool BoxShow::valid() const { bool BoxShow::valid() const {
return _weak; return resolve() && _wrapped->valid();
} }
BoxShow::operator bool() const { BoxShow::operator bool() const {

View file

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

View file

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

View file

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

View file

@ -6,7 +6,67 @@
// //
#include "ui/layers/layer_manager.h" #include "ui/layers/layer_manager.h"
#include "ui/layers/show.h"
namespace Ui { 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) { LayerManager::LayerManager(not_null<RpWidget*> widget) : _widget(widget) {
} }
@ -67,7 +127,9 @@ void LayerManager::ensureLayerCreated() {
if (_layer) { if (_layer) {
return; return;
} }
_layer.emplace(_widget); _layer.emplace(_widget, crl::guard(this, [=] {
return std::make_shared<ManagerShow>(this);
}));
_layer->setHideByBackgroundClick(_hideByBackgroundClick); _layer->setHideByBackgroundClick(_hideByBackgroundClick);
_layer->setStyleOverrides(_boxSt, _layerSt); _layer->setStyleOverrides(_boxSt, _layerSt);

View file

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

View file

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

View file

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

View file

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

View file

@ -425,7 +425,9 @@ void SeparatePanel::ensureLayerCreated() {
if (_layer) { if (_layer) {
return; 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->setHideByBackgroundClick(false);
_layer->move(0, 0); _layer->move(0, 0);
_body->sizeValue( _body->sizeValue(