mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-23 14:02:20 -04:00
UiService: Add is_selected for buttons (#2337)
This commit is contained in:
@@ -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)(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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] {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user