UiService: Add is_selected for buttons (#2337)

This commit is contained in:
Luke Street
2026-08-22 23:16:32 -06:00
committed by GitHub
parent 81dfe701e9
commit 3aa54ca170
6 changed files with 22 additions and 5 deletions
+5 -3
View File
@@ -9,7 +9,7 @@
#define UI_SERVICE_ID "dev.twilitrealm.dusklight.ui"
#define UI_SERVICE_MAJOR 1u
#define UI_SERVICE_MINOR 4u
#define UI_SERVICE_MINOR 5u
/*
* UI primitives: a panel inside the host Mods window, mod-owned windows, dialogs, toasts,
@@ -102,7 +102,7 @@ typedef struct UiControlDesc {
/* Optional override for the modified indicator. CONFIG_VAR controls derive it from value !=
* default when this is NULL. */
UiPredicateFn is_modified;
/* Passed to every callback above. */
/* Passed to every callback. */
void* user_data;
/* NUMBER: inclusive clamp range and step. min == max means the defaults (0 .. INT32_MAX); step
* < 1 means 1. */
@@ -121,11 +121,13 @@ typedef struct UiControlDesc {
const char* const* color_presets;
size_t color_preset_count;
bool color_alpha; /* COLOR: use RRGGBBAA values instead of RRGGBB */
/* Optional selected state for BUTTON/GROUP. Added in UiService minor version 5. */
UiPredicateFn is_selected;
} UiControlDesc;
#define UI_CONTROL_DESC_INIT \
{sizeof(UiControlDesc), UI_CONTROL_BUTTON, NULL, NULL, UI_BINDING_CALLBACKS, 0u, NULL, NULL, \
NULL, NULL, NULL, NULL, 0, 0, 1, NULL, NULL, NULL, 0u, 0, NULL, 0u, false}
NULL, NULL, NULL, NULL, 0, 0, 1, NULL, NULL, NULL, 0u, 0, NULL, 0u, false, NULL}
/* Build pane contents. A non-MOD_OK result fails the mod. */
typedef ModResult (*UiPaneBuildFn)(
+5 -1
View File
@@ -570,6 +570,9 @@ ModResult ui_pane_add_control(
case UI_CONTROL_GROUP:
spec.kind = desc.kind == UI_CONTROL_BUTTON ? ui::ModControlSpec::Kind::Button :
ui::ModControlSpec::Kind::Group;
if (desc.struct_size >= sizeof(UiControlDesc)) {
spec.isSelected = wrap_predicate(mod, desc.is_selected, desc.user_data, pane);
}
spec.onPressed = [modPtr = &mod, fn = desc.on_pressed, userData = desc.user_data,
guardHandle = pane] {
if (!slot_live(guardHandle)) {
@@ -1147,6 +1150,7 @@ bool valid_color_preset(const char* value, bool alpha) {
bool valid_control_desc(const UiControlDesc& desc) {
constexpr size_t kLegacyDescSize = offsetof(UiControlDesc, color_presets);
constexpr size_t kColorDescSize = offsetof(UiControlDesc, is_selected);
if (desc.struct_size < kLegacyDescSize || desc.label == nullptr) {
return false;
}
@@ -1160,7 +1164,7 @@ bool valid_control_desc(const UiControlDesc& desc) {
case UI_CONTROL_SELECT:
break;
case UI_CONTROL_COLOR:
if (desc.struct_size < sizeof(UiControlDesc)) {
if (desc.struct_size < kColorDescSize) {
return false;
}
break;
+6 -1
View File
@@ -4,15 +4,20 @@ namespace dusk::ui {
GroupButton::GroupButton(Rml::Element* parent, Props props)
: SelectButton{parent, {.key = std::move(props.text)}},
mIsDisabled{std::move(props.isDisabled)} {
mIsSelected{std::move(props.isSelected)}, mIsDisabled{std::move(props.isDisabled)} {
mRoot->SetClass("group-button", true);
}
void GroupButton::update() {
set_selected(selected());
set_disabled(disabled());
SelectButton::update();
}
bool GroupButton::selected() const {
return mIsSelected ? mIsSelected() : SelectButton::selected();
}
bool GroupButton::disabled() const {
return mIsDisabled ? mIsDisabled() : SelectButton::disabled();
}
+3
View File
@@ -8,15 +8,18 @@ class GroupButton : public SelectButton {
public:
struct Props {
Rml::String text;
std::function<bool()> isSelected;
std::function<bool()> isDisabled;
};
GroupButton(Rml::Element* parent, Props props);
void update() override;
bool selected() const override;
bool disabled() const override;
private:
std::function<bool()> mIsSelected;
std::function<bool()> mIsDisabled;
};
+2
View File
@@ -17,6 +17,7 @@ Component* build_mod_control(Pane& pane, Pane* helpPane, ModControlSpec spec) {
case ModControlSpec::Kind::Button:
control = &pane.add_button(ControlledButton::Props{
.text = s.label,
.isSelected = s.isSelected,
.isDisabled = s.isDisabled,
})
.on_pressed([shared] {
@@ -28,6 +29,7 @@ Component* build_mod_control(Pane& pane, Pane* helpPane, ModControlSpec spec) {
case ModControlSpec::Kind::Group:
control = &pane.add_group_button(GroupButton::Props{
.text = s.label,
.isSelected = s.isSelected,
.isDisabled = s.isDisabled,
})
.on_pressed([shared] {
+1
View File
@@ -29,6 +29,7 @@ struct ModControlSpec {
std::function<void(int)> setInt;
std::function<Rml::String()> getString;
std::function<void(Rml::String)> setString;
std::function<bool()> isSelected;
std::function<bool()> isDisabled;
std::function<bool()> isModified;
int min = 0;