// 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 #include "ui/layers/box_content.h" #include "ui/wrap/vertical_layout.h" #include namespace st { extern const style::margins &boxRowPadding; } // namespace st namespace Ui { class GenericBox final : public BoxContent { public: // InitMethod::operator()(not_null box, InitArgs...) // init(box, args...) template < typename InitMethod, typename ...InitArgs, typename = decltype(std::declval>()( std::declval>(), std::declval>()...))> GenericBox( QWidget*, InitMethod &&init, InitArgs &&...args); void setWidth(int width) { _width = width; } void setFocusCallback(Fn callback) { _focus = callback; } void setInitScrollCallback(Fn callback) { _initScroll = callback; } void setShowFinishedCallback(Fn callback) { _showFinished = callback; } [[nodiscard]] rpl::producer<> showFinishes() const { return _showFinishes.events(); } [[nodiscard]] int rowsCount() const; [[nodiscard]] int width() const; template < typename Widget, typename = std::enable_if_t< std::is_base_of_v>> Widget *insertRow( int atPosition, object_ptr &&child, const style::margins &margin = st::boxRowPadding) { return _content->insert( atPosition, std::move(child), margin); } template < typename Widget, typename = std::enable_if_t< std::is_base_of_v>> Widget *addRow( object_ptr &&child, const style::margins &margin = st::boxRowPadding) { return _content->add(std::move(child), margin); } void addSkip(int height); void setMaxHeight(int maxHeight) { _maxHeight = maxHeight; } void setMinHeight(int minHeight) { _minHeight = minHeight; } void setScrollStyle(const style::ScrollArea &st) { _scrollSt = &st; } void setInnerFocus() override; void showFinished() override; template not_null setPinnedToTopContent(object_ptr content) { return static_cast( doSetPinnedToTopContent(std::move(content)).get()); } template not_null setPinnedToBottomContent(object_ptr content) { return static_cast( doSetPinnedToBottomContent(std::move(content)).get()); } [[nodiscard]] not_null verticalLayout(); using BoxContent::setNoContentMargin; private: template struct Initer { template < typename OtherMethod, typename ...OtherArgs, typename = std::enable_if_t< std::is_constructible_v>> Initer(OtherMethod &&method, OtherArgs &&...args); void operator()(not_null box); template void call( not_null box, std::index_sequence); InitMethod method; std::tuple args; }; template auto MakeIniter(InitMethod &&method, InitArgs &&...args) -> Initer, std::decay_t...>; void prepare() override; not_null doSetPinnedToTopContent( object_ptr content); not_null doSetPinnedToBottomContent( object_ptr content); FnMut)> _init; Fn _focus; Fn _initScroll; Fn _showFinished; rpl::event_stream<> _showFinishes; object_ptr _owned; not_null _content; const style::ScrollArea *_scrollSt = nullptr; int _width = 0; int _minHeight = 0; int _maxHeight = 0; object_ptr _pinnedToTopContent = { nullptr }; object_ptr _pinnedToBottomContent = { nullptr }; }; template template GenericBox::Initer::Initer( OtherMethod &&method, OtherArgs &&...args) : method(std::forward(method)) , args(std::forward(args)...) { } template inline void GenericBox::Initer::operator()( not_null box) { call(box, std::make_index_sequence()); } template template inline void GenericBox::Initer::call( not_null box, std::index_sequence) { std::invoke(method, box, std::get(std::move(args))...); } template inline auto GenericBox::MakeIniter(InitMethod &&method, InitArgs &&...args) -> Initer, std::decay_t...> { return { std::forward(method), std::forward(args)... }; } template inline GenericBox::GenericBox( QWidget*, InitMethod &&init, InitArgs &&...args) : _init( MakeIniter( std::forward(init), std::forward(args)...)) , _owned(this) , _content(_owned.data()) { } [[nodiscard]] rpl::producer<> BoxShowFinishes(not_null box); } // namespace Ui