#pragma once #include "creeper-qt/utility/trait/widget.hh" #include "creeper-qt/utility/wrapper/common.hh" #include "creeper-qt/utility/wrapper/property.hh" namespace creeper::group::internal { template concept foreach_invoke_item_trait = requires { { std::invoke(std::declval(), std::declval()) } -> widget_pointer_trait; }; template concept foreach_apply_item_trait = requires { { std::apply(std::declval(), std::declval()) } -> widget_pointer_trait; }; template concept foreach_item_trait = foreach_invoke_item_trait || foreach_apply_item_trait; template concept foreach_invoke_ranges_trait = foreach_item_trait>; template struct Group : public T { using T::T; std::vector widgets; template requires foreach_invoke_ranges_trait constexpr auto compose(const R& ranges, F&& f, Qt::Alignment a = {}) noexcept -> void { for (const auto& item : ranges) { using ItemT = decltype(item); auto widget_pointer = (W*) {}; if constexpr (foreach_invoke_item_trait) widget_pointer = std::invoke(f, item); else if constexpr (foreach_apply_item_trait) widget_pointer = std::apply(f, item); if (widget_pointer != nullptr) { T::addWidget(widget_pointer, 0, a); widgets.push_back(widget_pointer); } } } auto foreach_(this auto&& self, auto&& f) noexcept requires std::invocable { for (auto widget : self.widgets) std::invoke(f, *widget); } }; }; namespace creeper::group::pro { using Token = common::Token>; /// @note /// 一种典型的用法,委托构造时,所传函数只能接受常量引用, /// 放心使用 auto,类型是可以被推导出来的 /// /// group::pro::Compose { /// std::array { /// std::tuple(1, "xxxxxx"), /// ...... /// }, /// [](auto index, auto text) { /// return new TextButton { ... }; /// }, /// } /// template requires internal::foreach_invoke_ranges_trait struct Compose : Token { const R& ranges; F method; Qt::Alignment alignment; explicit Compose(const R& r, F f, Qt::Alignment a = {}) noexcept : ranges { r } , method { std::move(f) } , alignment { a } { } auto apply(auto& self) noexcept -> void { // self.compose(ranges, std::move(method), alignment); } }; /// @note /// 函数参数是组件的引用: /// /// group::pro::Foreach { [](Widget& button) { ... } }, /// template requires(!std::invocable) struct Foreach : Token { F function; explicit Foreach(F&& f) noexcept : function { std::forward(f) } { } auto apply(auto& self) const noexcept { // 很遗憾,Qt 占用了 foreach 这个单词 self.foreach_(std::move(function)); } }; template concept trait = std::derived_from; CREEPER_DEFINE_CHECKER(trait) }; namespace creeper { template using Group = Declarative, CheckerOr>; }