Files
ts-qt/creeper-qt/layout/mutual-exclusion-group.hh
2025-11-25 15:59:47 +08:00

99 lines
3.3 KiB
C++

#pragma once
#include <creeper-qt/layout/group.hh>
#include <creeper-qt/utility/wrapper/layout.hh>
#include <ranges>
namespace creeper::mutual_exclusion_group::internal {
template <auto f, typename W>
concept switch_function_trait = std::invocable<decltype(f), W&, bool>;
template <layout_trait T, widget_trait W, auto switch_function>
requires switch_function_trait<switch_function, W>
struct MutualExclusionGroup : public Group<T, W> {
using Group<T, W>::Group;
public:
auto switch_widgets(std::size_t index) const noexcept {
for (auto [index_, w] : std::views::enumerate(this->widgets)) {
switch_function(*w, index_ == index);
}
}
auto switch_widgets(W* widget) const noexcept {
for (auto w_ : this->widgets) {
switch_function(*w_, w_ == widget);
}
}
auto make_signal_injection(auto signal) const noexcept -> void {
for (auto widget : this->widgets) {
QObject::connect(widget, signal, [this, widget] { switch_widgets(widget); });
}
}
};
constexpr inline auto checked_switch_function = [](auto& w, bool on) { w.set_checked(on); };
constexpr inline auto opened_switch_function = [](auto& w, bool on) { w.set_opened(on); };
constexpr inline auto selected_switch_function = [](auto& w, bool on) { w.set_selected(on); };
constexpr inline auto no_action_as_token = [](auto& w, bool on) { };
}
namespace creeper::mutual_exclusion_group::pro {
struct TokenContext { };
using Token = common::Token<TokenContext>;
template <typename Signal>
struct SignalInjection : Token {
Signal signal;
explicit SignalInjection(Signal signal) noexcept
: signal { signal } { }
auto apply(auto& self) const noexcept -> void {
self.make_signal_injection(signal); //
}
};
template <typename T>
concept trait = std::derived_from<T, Token> || group::pro::trait<T>;
CREEPER_DEFINE_CHECKER(trait);
using namespace group::pro;
}
namespace creeper {
template <layout_trait T, widget_trait W, auto switch_function>
requires mutual_exclusion_group::internal::switch_function_trait<switch_function, W>
using MutualExclusionGroup =
mutual_exclusion_group::internal::MutualExclusionGroup<T, W, switch_function>;
template <layout_trait T, widget_trait W>
using CheckGroup = Declarative<
MutualExclusionGroup<T, W, mutual_exclusion_group::internal::checked_switch_function>,
CheckerOr<mutual_exclusion_group::pro::checker, typename T::Checker>>;
namespace check_group = mutual_exclusion_group;
template <layout_trait T, widget_trait W>
using OpenGroup = Declarative<
MutualExclusionGroup<T, W, mutual_exclusion_group::internal::opened_switch_function>,
CheckerOr<mutual_exclusion_group::pro::checker, typename T::Checker>>;
namespace open_group = mutual_exclusion_group;
template <layout_trait T, widget_trait W>
using SelectGroup = Declarative<
MutualExclusionGroup<T, W, mutual_exclusion_group::internal::selected_switch_function>,
CheckerOr<mutual_exclusion_group::pro::checker, typename T::Checker>>;
namespace select_group = mutual_exclusion_group;
namespace internal {
inline auto use_mutual_exclusion_group_namespace() {
std::ignore = check_group::pro::Token {};
std::ignore = open_group::pro::Token {};
std::ignore = select_group::pro::Token {};
}
}
}