Added the ability for focus to set the current mod config option description (#576)

* Added the ability for focus to set the current mod config option description

* add focus to text input

* only clear description if element matches
This commit is contained in:
thecozies 2025-05-01 16:28:14 -05:00 committed by GitHub
parent 43811282d6
commit 7a59d7dca5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 79 additions and 16 deletions

View file

@ -37,6 +37,10 @@ namespace recompui {
pressed_callback = callback;
}
void RadioOption::set_focus_callback(std::function<void(bool)> callback) {
focus_callback = callback;
}
void RadioOption::set_selected_state(bool enable) {
set_style_enabled(checked_state, enable);
}
@ -67,6 +71,9 @@ namespace recompui {
if (active) {
queue_update();
}
if (focus_callback != nullptr) {
focus_callback(active);
}
}
break;
case EventType::Update:
@ -124,6 +131,9 @@ namespace recompui {
blur();
queue_child_focus();
}
if (focus_callback != nullptr) {
focus_callback(std::get<EventFocus>(e.variant).active);
}
}
break;
case EventType::Update:
@ -141,6 +151,11 @@ namespace recompui {
void Radio::add_option(std::string_view name) {
RadioOption *option = get_current_context().create_element<RadioOption>(this, name, uint32_t(options.size()));
option->set_pressed_callback([this](uint32_t index){ options[index]->focus(); option_selected(index); });
option->set_focus_callback([this](bool active) {
if (focus_callback != nullptr) {
focus_callback(active);
}
});
options.emplace_back(option);
// The first option was added, select it.
@ -165,6 +180,10 @@ namespace recompui {
void Radio::add_index_changed_callback(std::function<void(uint32_t)> callback) {
index_changed_callbacks.emplace_back(callback);
}
void Radio::set_focus_callback(std::function<void(bool)> callback) {
focus_callback = callback;
}
void Radio::set_nav_auto(NavDirection dir) {
Element::set_nav_auto(dir);
@ -246,4 +265,4 @@ namespace recompui {
}
}
};
};

View file

@ -10,6 +10,7 @@ namespace recompui {
Style checked_style;
Style pulsing_style;
std::function<void(uint32_t)> pressed_callback = nullptr;
std::function<void(bool)> focus_callback = nullptr;
uint32_t index = 0;
protected:
virtual void process_event(const Event &e) override;
@ -17,6 +18,7 @@ namespace recompui {
public:
RadioOption(Element *parent, std::string_view name, uint32_t index);
void set_pressed_callback(std::function<void(uint32_t)> callback);
void set_focus_callback(std::function<void(bool)> callback);
void set_selected_state(bool enable);
};
@ -25,6 +27,7 @@ namespace recompui {
std::vector<RadioOption *> options;
uint32_t index = 0;
std::vector<std::function<void(uint32_t)>> index_changed_callbacks;
std::function<void(bool)> focus_callback = nullptr;
bool child_focus_queued = false;
void set_index_internal(uint32_t index, bool setup, bool trigger_callbacks);
@ -42,6 +45,7 @@ namespace recompui {
void set_index(uint32_t index);
uint32_t get_index() const;
void add_index_changed_callback(std::function<void(uint32_t)> callback);
void set_focus_callback(std::function<void(bool)> callback);
size_t num_options() const { return options.size(); }
RadioOption* get_option_element(size_t option_index) { return options[option_index]; }
RadioOption* get_current_option_element() { return options.empty() ? nullptr : options[index]; }
@ -51,4 +55,4 @@ namespace recompui {
void set_nav_manual(NavDirection dir, const std::string& target) override;
};
} // namespace recompui
} // namespace recompui

View file

@ -81,6 +81,9 @@ namespace recompui {
if (active) {
queue_update();
}
if (focus_callback != nullptr) {
focus_callback(active);
}
}
break;
case EventType::Update:
@ -219,6 +222,10 @@ namespace recompui {
value_changed_callbacks.emplace_back(callback);
}
void Slider::set_focus_callback(std::function<void(bool)> callback) {
focus_callback = callback;
}
void Slider::do_step(bool increment) {
double new_value = value;
if (increment) {
@ -233,4 +240,4 @@ namespace recompui {
}
}
} // namespace recompui
} // namespace recompui

View file

@ -23,6 +23,7 @@ namespace recompui {
double max_value = 100.0;
double step_value = 0.0;
std::vector<std::function<void(double)>> value_changed_callbacks;
std::function<void(bool)> focus_callback = nullptr;
void set_value_internal(double v, bool setup, bool trigger_callbacks);
void bar_pressed(float x, float y);
@ -51,6 +52,7 @@ namespace recompui {
double get_step_value() const;
void add_value_changed_callback(std::function<void(double)> callback);
void do_step(bool increment);
void set_focus_callback(std::function<void(bool)> callback);
};
} // namespace recompui

View file

@ -16,12 +16,19 @@ namespace recompui {
break;
}
case EventType::Focus: {
const EventFocus &event = std::get<EventFocus>(e.variant);
if (focus_callback != nullptr) {
focus_callback(event.active);
}
break;
}
default:
break;
}
}
TextInput::TextInput(Element *parent, bool text_visible) : Element(parent, Events(EventType::Text), "input") {
TextInput::TextInput(Element *parent, bool text_visible) : Element(parent, Events(EventType::Text, EventType::Focus), "input") {
if (!text_visible) {
set_attribute("type", "password");
}
@ -48,4 +55,7 @@ namespace recompui {
text_changed_callbacks.emplace_back(callback);
}
};
void TextInput::set_focus_callback(std::function<void(bool)> callback) {
focus_callback = callback;
}
};

View file

@ -8,6 +8,7 @@ namespace recompui {
private:
std::string text;
std::vector<std::function<void(const std::string &)>> text_changed_callbacks;
std::function<void(bool)> focus_callback = nullptr;
protected:
virtual void process_event(const Event &e) override;
std::string_view get_type_name() override { return "TextInput"; }
@ -16,6 +17,7 @@ namespace recompui {
void set_text(std::string_view text);
const std::string &get_text();
void add_text_changed_callback(std::function<void(const std::string &)> callback);
void set_focus_callback(std::function<void(bool)> callback);
};
} // namespace recompui

View file

@ -13,6 +13,9 @@ namespace recompui {
void ConfigOptionElement::process_event(const Event &e) {
switch (e.type) {
case EventType::Hover:
if (hover_callback == nullptr) {
break;
}
hover_callback(this, std::get<EventHover>(e.variant).active);
break;
case EventType::Update:
@ -53,6 +56,10 @@ void ConfigOptionElement::set_hover_callback(std::function<void(ConfigOptionElem
hover_callback = callback;
}
void ConfigOptionElement::set_focus_callback(std::function<void(const std::string &, bool)> callback) {
focus_callback = callback;
}
const std::string &ConfigOptionElement::get_description() const {
return description;
}
@ -73,6 +80,9 @@ ConfigOptionSlider::ConfigOptionSlider(Element *parent, double value, double min
slider->set_step_value(step_value);
slider->set_value(value);
slider->add_value_changed_callback([this](double v){ slider_value_changed(v); });
slider->set_focus_callback([this](bool active) {
focus_callback(option_id, active);
});
}
// ConfigOptionTextInput
@ -88,6 +98,9 @@ ConfigOptionTextInput::ConfigOptionTextInput(Element *parent, std::string_view v
text_input->set_max_width(400.0f);
text_input->set_text(value);
text_input->add_text_changed_callback([this](const std::string &text){ text_changed(text); });
text_input->set_focus_callback([this](bool active) {
focus_callback(option_id, active);
});
}
// ConfigOptionRadio
@ -100,6 +113,9 @@ ConfigOptionRadio::ConfigOptionRadio(Element *parent, uint32_t value, const std:
this->callback = callback;
radio = get_current_context().create_element<Radio>(this);
radio->set_focus_callback([this](bool active) {
focus_callback(option_id, active);
});
radio->add_index_changed_callback([this](uint32_t index){ index_changed(index); });
for (std::string_view option : options) {
radio->add_option(option);
@ -122,19 +138,19 @@ void ConfigSubMenu::back_button_pressed() {
recompui::focus_mod_configure_button();
}
void ConfigSubMenu::option_hovered(ConfigOptionElement *option, bool active) {
void ConfigSubMenu::set_description_option_element(ConfigOptionElement *option, bool active) {
if (active) {
hover_option_elements.emplace(option);
description_option_element = option;
}
else {
hover_option_elements.erase(option);
else if (description_option_element == option) {
description_option_element = nullptr;
}
if (hover_option_elements.empty()) {
if (description_option_element == nullptr) {
description_label->set_text("");
}
else {
description_label->set_text((*hover_option_elements.begin())->get_description());
description_label->set_text(description_option_element->get_description());
}
}
@ -190,14 +206,15 @@ void ConfigSubMenu::enter(std::string_view title) {
void ConfigSubMenu::clear_options() {
config_scroll_container->clear_children();
config_option_elements.clear();
hover_option_elements.clear();
description_option_element = nullptr;
}
void ConfigSubMenu::add_option(ConfigOptionElement *option, std::string_view id, std::string_view name, std::string_view description) {
option->set_option_id(id);
option->set_name(name);
option->set_description(description);
option->set_hover_callback([this](ConfigOptionElement *option, bool active){ option_hovered(option, active); });
option->set_hover_callback([this](ConfigOptionElement *option, bool active){ set_description_option_element(option, active); });
option->set_focus_callback([this, option](const std::string &id, bool active) { set_description_option_element(option, active); });
if (config_option_elements.empty()) {
back_button->set_nav(NavDirection::Down, option->get_focus_element());
option->set_nav(NavDirection::Up, back_button);

View file

@ -20,6 +20,7 @@ protected:
std::string name;
std::string description;
std::function<void(ConfigOptionElement *, bool)> hover_callback = nullptr;
std::function<void(const std::string &, bool)> focus_callback = nullptr;
virtual void process_event(const Event &e) override;
std::string_view get_type_name() override { return "ConfigOptionElement"; }
@ -30,6 +31,7 @@ public:
void set_name(std::string_view name);
void set_description(std::string_view description);
void set_hover_callback(std::function<void(ConfigOptionElement *, bool)> callback);
void set_focus_callback(std::function<void(const std::string &, bool)> callback);
const std::string &get_description() const;
void set_nav_auto(NavDirection dir) override { get_focus_element()->set_nav_auto(dir); }
void set_nav_none(NavDirection dir) override { get_focus_element()->set_nav_none(dir); }
@ -84,10 +86,10 @@ private:
Container *config_container = nullptr;
ScrollContainer *config_scroll_container = nullptr;
std::vector<ConfigOptionElement *> config_option_elements;
std::unordered_set<ConfigOptionElement *> hover_option_elements;
ConfigOptionElement * description_option_element = nullptr;
void back_button_pressed();
void option_hovered(ConfigOptionElement *option, bool active);
void set_description_option_element(ConfigOptionElement *option, bool active);
void add_option(ConfigOptionElement *option, std::string_view id, std::string_view name, std::string_view description);
protected:
std::string_view get_type_name() override { return "ConfigSubMenu"; }
@ -112,4 +114,4 @@ private:
};
}
#endif
#endif