/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include #include #include #include "base/unique_qptr.h" namespace Ui { namespace details { template class AttachmentOwner : public QObject { public: template AttachmentOwner(QObject *parent, OtherValue &&value) : QObject(parent) , _value(std::forward(value)) { } private: Value _value; }; } // namespace details template inline base::unique_qptr CreateObject(Args &&...args) { return base::make_unique_q( nullptr, std::forward(args)...); } template inline Widget *CreateChild( Parent *parent, Args &&...args) { Expects(parent != nullptr); return new Widget(parent, std::forward(args)...); } inline void DestroyChild(QWidget *child) { delete child; } template inline void AttachAsChild(not_null parent, Value &&value) { using PlainValue = std::decay_t; CreateChild>( parent.get(), std::forward(value)); } template using RpWidgetParent = std::conditional_t< std::is_same_v, TWidget, TWidgetHelper>; template class RpWidgetWrap; class RpWidgetMethods { public: rpl::producer geometryValue() const; rpl::producer sizeValue() const; rpl::producer heightValue() const; rpl::producer widthValue() const; rpl::producer positionValue() const; rpl::producer leftValue() const; rpl::producer topValue() const; virtual rpl::producer desiredHeightValue() const; rpl::producer shownValue() const; rpl::producer paintRequest() const; rpl::producer<> alive() const; template void showOn(rpl::producer &&shown) { std::move( shown ) | rpl::start_with_next([this](bool visible) { callSetVisible(visible); }, lifetime()); } rpl::lifetime &lifetime(); protected: bool handleEvent(QEvent *event); virtual bool eventHook(QEvent *event) = 0; private: template friend class RpWidgetWrap; struct EventStreams { rpl::event_stream geometry; rpl::event_stream paint; rpl::event_stream shown; rpl::event_stream<> alive; }; struct Initer { Initer(QWidget *parent); }; virtual void callSetVisible(bool visible) = 0; virtual QPointer callCreateWeak() = 0; virtual QRect callGetGeometry() const = 0; virtual bool callIsHidden() const = 0; void visibilityChangedHook(bool wasVisible, bool nowVisible); EventStreams &eventStreams() const; mutable std::unique_ptr _eventStreams; rpl::lifetime _lifetime; }; template class RpWidgetWrap : public RpWidgetParent , public RpWidgetMethods { using Self = RpWidgetWrap; using Parent = RpWidgetParent; public: using Parent::Parent; void setVisible(bool visible) final override { auto wasVisible = !this->isHidden(); setVisibleHook(visible); visibilityChangedHook(wasVisible, !this->isHidden()); } ~RpWidgetWrap() { base::take(_lifetime); base::take(_eventStreams); } protected: bool event(QEvent *event) final override { return handleEvent(event); } bool eventHook(QEvent *event) override { return Parent::event(event); } virtual void setVisibleHook(bool visible) { Parent::setVisible(visible); } private: void callSetVisible(bool visible) override { Self::setVisible(visible); } QPointer callCreateWeak() override { return QPointer((QObject*)this); } QRect callGetGeometry() const override { return this->geometry(); } bool callIsHidden() const override { return this->isHidden(); } Initer _initer = { this }; }; class RpWidget : public RpWidgetWrap { public: using RpWidgetWrap::RpWidgetWrap; }; } // namespace Ui