#pragma once #include "modern-qt/utility/trait/widget.hh" #include "modern-qt/utility/wrapper/common.hh" #include "modern-qt/utility/wrapper/layout.hh" #include "modern-qt/utility/wrapper/property.hh" #include namespace creeper::linear::pro { using Token = common::Token; struct SpacingItem : Token { int size; explicit SpacingItem(int p) { size = p; } void apply(QBoxLayout& self) const { self.addSpacing(size); } }; struct Stretch : Token { int stretch; explicit Stretch(int p) { stretch = p; } void apply(QBoxLayout& self) const { self.addStretch(stretch); } }; struct SpacerItem : Token { QSpacerItem* spacer_item; explicit SpacerItem(QSpacerItem* p) { spacer_item = p; } void apply(QBoxLayout& self) const { self.addSpacerItem(spacer_item); } }; /// @brief /// 布局项包装器,用于声明式地将 Widget 或 Layout 添加到布局中 /// /// @tparam T /// 被包装的组件类型,需满足可转换为 QWidget* 或 QLayout*,不需 /// 要显式指定,由构造参数推倒 /// /// @note /// Item 提供统一的接口用于在布局中插入控件或子布局, /// 支持多种构造方式,包括直接传入指针或通过参数构造新对象。 /// 通过 LayoutMethod 可指定拉伸因子和对齐方式, /// 在布局应用时自动选择 addWidget 或 addLayout, /// 实现非侵入式的布局声明式封装。 /// /// 示例用途: /// linear::pro::Item { /// { 0, Qt::AlignHCenter } // stretch, and alignment, optional /// ... /// }; /// template struct Item : Token { struct LayoutMethod { int stretch = 0; Qt::Alignment align = {}; } method; T* item_pointer = nullptr; explicit Item(const LayoutMethod& method, T* pointer) noexcept : item_pointer { pointer } , method { method } { } explicit Item(T* pointer) noexcept : item_pointer { pointer } { } explicit Item(const LayoutMethod& method, auto&&... args) noexcept requires std::constructible_from : item_pointer { new T { std::forward(args)... } } , method(method) { } explicit Item(auto&&... args) noexcept requires std::constructible_from : item_pointer { new T { std::forward(args)... } } { } void apply(linear_trait auto& layout) const { if constexpr (widget_trait) layout.addWidget(item_pointer, method.stretch, method.align); if constexpr (layout_trait) layout.addLayout(item_pointer, method.stretch); } }; template concept trait = std::derived_from; CREEPER_DEFINE_CHECKER(trait); using namespace layout::pro; } namespace creeper { template using BoxLayout = Declarative>; using Row = BoxLayout; using Col = BoxLayout; namespace row = linear; namespace col = linear; namespace internal { inline auto use_the_namespace_alias_to_eliminate_warnings() { std::ignore = row::pro::Token {}; std::ignore = col::pro::Token {}; } } }