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; | ||||
|     } | ||||
| 
 | ||||
|     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.
 | ||||
|  | @ -166,6 +181,10 @@ namespace recompui { | |||
|         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); | ||||
|         if (!options.empty()) { | ||||
|  |  | |||
|  | @ -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]; } | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
| }; | ||||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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"; } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 thecozies
						thecozies