mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp.git
synced 2025-10-30 08:03:03 +00:00
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:
parent
43811282d6
commit
7a59d7dca5
8 changed files with 79 additions and 16 deletions
|
|
@ -37,6 +37,10 @@ namespace recompui {
|
||||||
pressed_callback = callback;
|
pressed_callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RadioOption::set_focus_callback(std::function<void(bool)> callback) {
|
||||||
|
focus_callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
void RadioOption::set_selected_state(bool enable) {
|
void RadioOption::set_selected_state(bool enable) {
|
||||||
set_style_enabled(checked_state, enable);
|
set_style_enabled(checked_state, enable);
|
||||||
}
|
}
|
||||||
|
|
@ -67,6 +71,9 @@ namespace recompui {
|
||||||
if (active) {
|
if (active) {
|
||||||
queue_update();
|
queue_update();
|
||||||
}
|
}
|
||||||
|
if (focus_callback != nullptr) {
|
||||||
|
focus_callback(active);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EventType::Update:
|
case EventType::Update:
|
||||||
|
|
@ -124,6 +131,9 @@ namespace recompui {
|
||||||
blur();
|
blur();
|
||||||
queue_child_focus();
|
queue_child_focus();
|
||||||
}
|
}
|
||||||
|
if (focus_callback != nullptr) {
|
||||||
|
focus_callback(std::get<EventFocus>(e.variant).active);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EventType::Update:
|
case EventType::Update:
|
||||||
|
|
@ -141,6 +151,11 @@ namespace recompui {
|
||||||
void Radio::add_option(std::string_view name) {
|
void Radio::add_option(std::string_view name) {
|
||||||
RadioOption *option = get_current_context().create_element<RadioOption>(this, name, uint32_t(options.size()));
|
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_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);
|
options.emplace_back(option);
|
||||||
|
|
||||||
// The first option was added, select it.
|
// The first option was added, select it.
|
||||||
|
|
@ -166,6 +181,10 @@ namespace recompui {
|
||||||
index_changed_callbacks.emplace_back(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) {
|
void Radio::set_nav_auto(NavDirection dir) {
|
||||||
Element::set_nav_auto(dir);
|
Element::set_nav_auto(dir);
|
||||||
if (!options.empty()) {
|
if (!options.empty()) {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ namespace recompui {
|
||||||
Style checked_style;
|
Style checked_style;
|
||||||
Style pulsing_style;
|
Style pulsing_style;
|
||||||
std::function<void(uint32_t)> pressed_callback = nullptr;
|
std::function<void(uint32_t)> pressed_callback = nullptr;
|
||||||
|
std::function<void(bool)> focus_callback = nullptr;
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
protected:
|
protected:
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
|
|
@ -17,6 +18,7 @@ namespace recompui {
|
||||||
public:
|
public:
|
||||||
RadioOption(Element *parent, std::string_view name, uint32_t index);
|
RadioOption(Element *parent, std::string_view name, uint32_t index);
|
||||||
void set_pressed_callback(std::function<void(uint32_t)> callback);
|
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);
|
void set_selected_state(bool enable);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -25,6 +27,7 @@ namespace recompui {
|
||||||
std::vector<RadioOption *> options;
|
std::vector<RadioOption *> options;
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
std::vector<std::function<void(uint32_t)>> index_changed_callbacks;
|
std::vector<std::function<void(uint32_t)>> index_changed_callbacks;
|
||||||
|
std::function<void(bool)> focus_callback = nullptr;
|
||||||
bool child_focus_queued = false;
|
bool child_focus_queued = false;
|
||||||
|
|
||||||
void set_index_internal(uint32_t index, bool setup, bool trigger_callbacks);
|
void set_index_internal(uint32_t index, bool setup, bool trigger_callbacks);
|
||||||
|
|
@ -42,6 +45,7 @@ namespace recompui {
|
||||||
void set_index(uint32_t index);
|
void set_index(uint32_t index);
|
||||||
uint32_t get_index() const;
|
uint32_t get_index() const;
|
||||||
void add_index_changed_callback(std::function<void(uint32_t)> callback);
|
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(); }
|
size_t num_options() const { return options.size(); }
|
||||||
RadioOption* get_option_element(size_t option_index) { return options[option_index]; }
|
RadioOption* get_option_element(size_t option_index) { return options[option_index]; }
|
||||||
RadioOption* get_current_option_element() { return options.empty() ? nullptr : options[index]; }
|
RadioOption* get_current_option_element() { return options.empty() ? nullptr : options[index]; }
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,9 @@ namespace recompui {
|
||||||
if (active) {
|
if (active) {
|
||||||
queue_update();
|
queue_update();
|
||||||
}
|
}
|
||||||
|
if (focus_callback != nullptr) {
|
||||||
|
focus_callback(active);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EventType::Update:
|
case EventType::Update:
|
||||||
|
|
@ -219,6 +222,10 @@ namespace recompui {
|
||||||
value_changed_callbacks.emplace_back(callback);
|
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) {
|
void Slider::do_step(bool increment) {
|
||||||
double new_value = value;
|
double new_value = value;
|
||||||
if (increment) {
|
if (increment) {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ namespace recompui {
|
||||||
double max_value = 100.0;
|
double max_value = 100.0;
|
||||||
double step_value = 0.0;
|
double step_value = 0.0;
|
||||||
std::vector<std::function<void(double)>> value_changed_callbacks;
|
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 set_value_internal(double v, bool setup, bool trigger_callbacks);
|
||||||
void bar_pressed(float x, float y);
|
void bar_pressed(float x, float y);
|
||||||
|
|
@ -51,6 +52,7 @@ namespace recompui {
|
||||||
double get_step_value() const;
|
double get_step_value() const;
|
||||||
void add_value_changed_callback(std::function<void(double)> callback);
|
void add_value_changed_callback(std::function<void(double)> callback);
|
||||||
void do_step(bool increment);
|
void do_step(bool increment);
|
||||||
|
void set_focus_callback(std::function<void(bool)> callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace recompui
|
} // namespace recompui
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,19 @@ namespace recompui {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EventType::Focus: {
|
||||||
|
const EventFocus &event = std::get<EventFocus>(e.variant);
|
||||||
|
if (focus_callback != nullptr) {
|
||||||
|
focus_callback(event.active);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
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) {
|
if (!text_visible) {
|
||||||
set_attribute("type", "password");
|
set_attribute("type", "password");
|
||||||
}
|
}
|
||||||
|
|
@ -48,4 +55,7 @@ namespace recompui {
|
||||||
text_changed_callbacks.emplace_back(callback);
|
text_changed_callbacks.emplace_back(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextInput::set_focus_callback(std::function<void(bool)> callback) {
|
||||||
|
focus_callback = callback;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -8,6 +8,7 @@ namespace recompui {
|
||||||
private:
|
private:
|
||||||
std::string text;
|
std::string text;
|
||||||
std::vector<std::function<void(const std::string &)>> text_changed_callbacks;
|
std::vector<std::function<void(const std::string &)>> text_changed_callbacks;
|
||||||
|
std::function<void(bool)> focus_callback = nullptr;
|
||||||
protected:
|
protected:
|
||||||
virtual void process_event(const Event &e) override;
|
virtual void process_event(const Event &e) override;
|
||||||
std::string_view get_type_name() override { return "TextInput"; }
|
std::string_view get_type_name() override { return "TextInput"; }
|
||||||
|
|
@ -16,6 +17,7 @@ namespace recompui {
|
||||||
void set_text(std::string_view text);
|
void set_text(std::string_view text);
|
||||||
const std::string &get_text();
|
const std::string &get_text();
|
||||||
void add_text_changed_callback(std::function<void(const std::string &)> callback);
|
void add_text_changed_callback(std::function<void(const std::string &)> callback);
|
||||||
|
void set_focus_callback(std::function<void(bool)> callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace recompui
|
} // namespace recompui
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ namespace recompui {
|
||||||
void ConfigOptionElement::process_event(const Event &e) {
|
void ConfigOptionElement::process_event(const Event &e) {
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case EventType::Hover:
|
case EventType::Hover:
|
||||||
|
if (hover_callback == nullptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
hover_callback(this, std::get<EventHover>(e.variant).active);
|
hover_callback(this, std::get<EventHover>(e.variant).active);
|
||||||
break;
|
break;
|
||||||
case EventType::Update:
|
case EventType::Update:
|
||||||
|
|
@ -53,6 +56,10 @@ void ConfigOptionElement::set_hover_callback(std::function<void(ConfigOptionElem
|
||||||
hover_callback = callback;
|
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 {
|
const std::string &ConfigOptionElement::get_description() const {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
@ -73,6 +80,9 @@ ConfigOptionSlider::ConfigOptionSlider(Element *parent, double value, double min
|
||||||
slider->set_step_value(step_value);
|
slider->set_step_value(step_value);
|
||||||
slider->set_value(value);
|
slider->set_value(value);
|
||||||
slider->add_value_changed_callback([this](double v){ slider_value_changed(v); });
|
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
|
// ConfigOptionTextInput
|
||||||
|
|
@ -88,6 +98,9 @@ ConfigOptionTextInput::ConfigOptionTextInput(Element *parent, std::string_view v
|
||||||
text_input->set_max_width(400.0f);
|
text_input->set_max_width(400.0f);
|
||||||
text_input->set_text(value);
|
text_input->set_text(value);
|
||||||
text_input->add_text_changed_callback([this](const std::string &text){ text_changed(text); });
|
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
|
// ConfigOptionRadio
|
||||||
|
|
@ -100,6 +113,9 @@ ConfigOptionRadio::ConfigOptionRadio(Element *parent, uint32_t value, const std:
|
||||||
this->callback = callback;
|
this->callback = callback;
|
||||||
|
|
||||||
radio = get_current_context().create_element<Radio>(this);
|
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); });
|
radio->add_index_changed_callback([this](uint32_t index){ index_changed(index); });
|
||||||
for (std::string_view option : options) {
|
for (std::string_view option : options) {
|
||||||
radio->add_option(option);
|
radio->add_option(option);
|
||||||
|
|
@ -122,19 +138,19 @@ void ConfigSubMenu::back_button_pressed() {
|
||||||
recompui::focus_mod_configure_button();
|
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) {
|
if (active) {
|
||||||
hover_option_elements.emplace(option);
|
description_option_element = option;
|
||||||
}
|
}
|
||||||
else {
|
else if (description_option_element == option) {
|
||||||
hover_option_elements.erase(option);
|
description_option_element = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hover_option_elements.empty()) {
|
if (description_option_element == nullptr) {
|
||||||
description_label->set_text("");
|
description_label->set_text("");
|
||||||
}
|
}
|
||||||
else {
|
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() {
|
void ConfigSubMenu::clear_options() {
|
||||||
config_scroll_container->clear_children();
|
config_scroll_container->clear_children();
|
||||||
config_option_elements.clear();
|
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) {
|
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_option_id(id);
|
||||||
option->set_name(name);
|
option->set_name(name);
|
||||||
option->set_description(description);
|
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()) {
|
if (config_option_elements.empty()) {
|
||||||
back_button->set_nav(NavDirection::Down, option->get_focus_element());
|
back_button->set_nav(NavDirection::Down, option->get_focus_element());
|
||||||
option->set_nav(NavDirection::Up, back_button);
|
option->set_nav(NavDirection::Up, back_button);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ protected:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string description;
|
std::string description;
|
||||||
std::function<void(ConfigOptionElement *, bool)> hover_callback = nullptr;
|
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;
|
virtual void process_event(const Event &e) override;
|
||||||
std::string_view get_type_name() override { return "ConfigOptionElement"; }
|
std::string_view get_type_name() override { return "ConfigOptionElement"; }
|
||||||
|
|
@ -30,6 +31,7 @@ public:
|
||||||
void set_name(std::string_view name);
|
void set_name(std::string_view name);
|
||||||
void set_description(std::string_view description);
|
void set_description(std::string_view description);
|
||||||
void set_hover_callback(std::function<void(ConfigOptionElement *, bool)> callback);
|
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;
|
const std::string &get_description() const;
|
||||||
void set_nav_auto(NavDirection dir) override { get_focus_element()->set_nav_auto(dir); }
|
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); }
|
void set_nav_none(NavDirection dir) override { get_focus_element()->set_nav_none(dir); }
|
||||||
|
|
@ -84,10 +86,10 @@ private:
|
||||||
Container *config_container = nullptr;
|
Container *config_container = nullptr;
|
||||||
ScrollContainer *config_scroll_container = nullptr;
|
ScrollContainer *config_scroll_container = nullptr;
|
||||||
std::vector<ConfigOptionElement *> config_option_elements;
|
std::vector<ConfigOptionElement *> config_option_elements;
|
||||||
std::unordered_set<ConfigOptionElement *> hover_option_elements;
|
ConfigOptionElement * description_option_element = nullptr;
|
||||||
|
|
||||||
void back_button_pressed();
|
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);
|
void add_option(ConfigOptionElement *option, std::string_view id, std::string_view name, std::string_view description);
|
||||||
protected:
|
protected:
|
||||||
std::string_view get_type_name() override { return "ConfigSubMenu"; }
|
std::string_view get_type_name() override { return "ConfigSubMenu"; }
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue