Implement tabbing between fields in GUI2 dialogs
Unfortunately, each dialog currently needs to manually set up the tab order, but this is at least better than nothing.
This commit is contained in:
parent
f24a0307b9
commit
38774f4dd4
13 changed files with 113 additions and 5 deletions
|
@ -1,4 +1,6 @@
|
|||
Version 1.13.8+dev:
|
||||
* User Interface:
|
||||
* Enable the use of tab to switch between text fields in most dialogs.
|
||||
|
||||
Version 1.13.8:
|
||||
* Campaigns:
|
||||
|
|
|
@ -551,7 +551,7 @@ distributor::distributor(widget& owner,
|
|||
, tooltip_(0)
|
||||
, help_popup_(0)
|
||||
#endif
|
||||
, keyboard_focus_(0)
|
||||
, keyboard_focus_(nullptr)
|
||||
, keyboard_focus_chain_()
|
||||
{
|
||||
if(SDL_WasInit(SDL_INIT_TIMER) == 0) {
|
||||
|
@ -589,6 +589,11 @@ void distributor::initialize_state()
|
|||
init_mouse_location();
|
||||
}
|
||||
|
||||
widget* distributor::keyboard_focus() const
|
||||
{
|
||||
return keyboard_focus_;
|
||||
}
|
||||
|
||||
void distributor::keyboard_capture(widget* widget)
|
||||
{
|
||||
if(keyboard_focus_) {
|
||||
|
|
|
@ -297,6 +297,11 @@ public:
|
|||
*/
|
||||
void keyboard_remove_from_chain(widget* widget);
|
||||
|
||||
/**
|
||||
* Return the widget currently capturing keyboard input.
|
||||
*/
|
||||
widget* keyboard_focus() const;
|
||||
|
||||
private:
|
||||
class layer : public video2::draw_layering
|
||||
{
|
||||
|
|
|
@ -123,6 +123,9 @@ void custom_tod::pre_show(window& window)
|
|||
{"sound", tod_getter_sound}
|
||||
};
|
||||
|
||||
window.add_to_tab_order(find_widget<text_box>(&window, "tod_name", false, false));
|
||||
window.add_to_tab_order(find_widget<text_box>(&window, "tod_id", false, false));
|
||||
|
||||
for(const auto& data : metadata_stuff) {
|
||||
find_widget<text_box>(&window, "path_" + data.first, false).set_active(false);
|
||||
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
#include "gui/dialogs/editor/edit_label.hpp"
|
||||
|
||||
#include "gui/auxiliary/find_widget.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/text_box.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
|
||||
#include "utils/functional.hpp"
|
||||
|
||||
|
@ -81,6 +84,12 @@ editor_edit_label::editor_edit_label(std::string& text,
|
|||
register_color_component("slider_blue", &color_t::b);
|
||||
}
|
||||
|
||||
void editor_edit_label::pre_show(window& win)
|
||||
{
|
||||
win.add_to_tab_order(find_widget<text_box>(&win, "label", false, false));
|
||||
win.add_to_tab_order(find_widget<text_box>(&win, "category", false, false));
|
||||
}
|
||||
|
||||
void editor_edit_label::register_color_component(std::string widget_id, uint8_t color_t::* component) {
|
||||
register_integer(widget_id, true,
|
||||
std::bind(&editor_edit_label::load_color_component, this, component),
|
||||
|
|
|
@ -62,6 +62,8 @@ private:
|
|||
void register_color_component(std::string widget_id, uint8_t color_t::* component);
|
||||
/** Inherited from modal_dialog, implemented by REGISTER_DIALOG. */
|
||||
virtual const std::string& window_id() const override;
|
||||
/** Inherited from modal_dialog. */
|
||||
virtual void pre_show(window& window) override;
|
||||
};
|
||||
} // namespace dialogs
|
||||
} // namespace gui2
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
#include "gui/dialogs/editor/edit_scenario.hpp"
|
||||
|
||||
#include "gui/auxiliary/find_widget.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/text_box.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
@ -67,5 +70,13 @@ editor_edit_scenario::editor_edit_scenario(
|
|||
victory_when_enemies_defeated);
|
||||
register_bool("random_start_time", true, random_start_time);
|
||||
}
|
||||
|
||||
void editor_edit_scenario::pre_show(window& win)
|
||||
{
|
||||
win.add_to_tab_order(find_widget<text_box>(&win, "id", false, false));
|
||||
win.add_to_tab_order(find_widget<text_box>(&win, "name", false, false));
|
||||
win.add_to_tab_order(find_widget<text_box>(&win, "description", false, false));
|
||||
}
|
||||
|
||||
} // namespace dialogs
|
||||
} // namespace gui2
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
private:
|
||||
/** Inherited from modal_dialog, implemented by REGISTER_DIALOG. */
|
||||
virtual const std::string& window_id() const override;
|
||||
/** Inherited from modal_dialog. */
|
||||
virtual void pre_show(window& window) override;
|
||||
};
|
||||
} // namespace dialogs
|
||||
} // namespace gui2
|
||||
|
|
|
@ -87,6 +87,9 @@ void editor_edit_side::pre_show(window& window)
|
|||
vision_group.add_member(&find_widget<toggle_button>(&window, "vision_null", false), team::SHARE_VISION::NONE);
|
||||
|
||||
vision_group.set_member_states(share_vision_);
|
||||
|
||||
window.add_to_tab_order(find_widget<text_box>(&window, "team_name", false, false));
|
||||
window.add_to_tab_order(find_widget<text_box>(&window, "user_team_name", false, false));
|
||||
}
|
||||
|
||||
void editor_edit_side::post_show(window&)
|
||||
|
|
|
@ -112,6 +112,8 @@ void lobby_player_info::pre_show(window& window)
|
|||
|
||||
time_ = find_widget<text_box>(&window, "time", false, true);
|
||||
reason_ = find_widget<text_box>(&window, "reason", false, true);
|
||||
window.add_to_tab_order(reason_);
|
||||
window.add_to_tab_order(time_);
|
||||
|
||||
find_widget<label>(&window, "location_info", false).set_label(loc.str());
|
||||
|
||||
|
|
|
@ -93,6 +93,9 @@ void mp_login::pre_show(window& win)
|
|||
|
||||
btn->set_retval(2);
|
||||
}
|
||||
|
||||
win.add_to_tab_order(find_widget<text_box>(&win, "user_name", false, false));
|
||||
win.add_to_tab_order(find_widget<text_box>(&win, "password", false, false));
|
||||
}
|
||||
|
||||
void mp_login::post_show(window& win)
|
||||
|
|
|
@ -389,10 +389,10 @@ window::window(CVideo& video,
|
|||
|
||||
connect_signal<event::SDL_KEY_DOWN>(
|
||||
std::bind(
|
||||
&window::signal_handler_sdl_key_down, this, _2, _3, _5),
|
||||
&window::signal_handler_sdl_key_down, this, _2, _3, _5, _6, true),
|
||||
event::dispatcher::back_post_child);
|
||||
connect_signal<event::SDL_KEY_DOWN>(std::bind(
|
||||
&window::signal_handler_sdl_key_down, this, _2, _3, _5));
|
||||
&window::signal_handler_sdl_key_down, this, _2, _3, _5, _6, false));
|
||||
|
||||
connect_signal<event::MESSAGE_SHOW_TOOLTIP>(
|
||||
std::bind(&window::signal_handler_message_show_tooltip,
|
||||
|
@ -1340,6 +1340,22 @@ void window::remove_from_keyboard_chain(widget* widget)
|
|||
event_distributor_->keyboard_remove_from_chain(widget);
|
||||
}
|
||||
|
||||
void window::add_to_tab_order(widget* widget, int at)
|
||||
{
|
||||
if(std::find(tab_order.begin(), tab_order.end(), widget) != tab_order.end()) {
|
||||
return;
|
||||
}
|
||||
assert(event_distributor_);
|
||||
if(tab_order.empty() && !event_distributor_->keyboard_focus()) {
|
||||
keyboard_capture(widget);
|
||||
}
|
||||
if(at < 0 || at >= static_cast<int>(tab_order.size())) {
|
||||
tab_order.push_back(widget);
|
||||
} else {
|
||||
tab_order.insert(tab_order.begin() + at, widget);
|
||||
}
|
||||
}
|
||||
|
||||
void window::signal_handler_sdl_video_resize(const event::ui_event event,
|
||||
bool& handled,
|
||||
const point& new_size)
|
||||
|
@ -1366,9 +1382,19 @@ void window::signal_handler_click_dismiss(const event::ui_event event,
|
|||
handled = halt = click_dismiss(mouse_button_mask);
|
||||
}
|
||||
|
||||
static bool is_active(const widget* wgt)
|
||||
{
|
||||
if(const styled_widget* control = dynamic_cast<const styled_widget*>(wgt)) {
|
||||
return control->get_active() && control->get_visible() == window::visibility::visible;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void window::signal_handler_sdl_key_down(const event::ui_event event,
|
||||
bool& handled,
|
||||
SDL_Keycode key)
|
||||
const SDL_Keycode key,
|
||||
const SDL_Keymod mod,
|
||||
bool handle_tab)
|
||||
{
|
||||
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
|
||||
|
||||
|
@ -1380,6 +1406,29 @@ void window::signal_handler_sdl_key_down(const event::ui_event event,
|
|||
handled = true;
|
||||
} else if(key == SDLK_SPACE) {
|
||||
handled = click_dismiss(0);
|
||||
} else if(handle_tab && !tab_order.empty() && key == SDLK_TAB) {
|
||||
assert(event_distributor_);
|
||||
widget* focus = event_distributor_->keyboard_focus();
|
||||
auto iter = std::find(tab_order.begin(), tab_order.end(), focus);
|
||||
do {
|
||||
if(mod & KMOD_SHIFT) {
|
||||
if(iter == tab_order.begin()) {
|
||||
iter = tab_order.end();
|
||||
}
|
||||
iter--;
|
||||
} else {
|
||||
if(iter == tab_order.end()) {
|
||||
iter = tab_order.begin();
|
||||
} else {
|
||||
iter++;
|
||||
if(iter == tab_order.end()) {
|
||||
iter = tab_order.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(!is_active(*iter));
|
||||
keyboard_capture(*iter);
|
||||
handled = true;
|
||||
}
|
||||
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
|
||||
if(key == SDLK_F12) {
|
||||
|
|
|
@ -643,6 +643,9 @@ private:
|
|||
/** List of the widgets, whose size are linked together. */
|
||||
std::map<std::string, linked_size> linked_size_;
|
||||
|
||||
/** List of widgets in the tabbing order. */
|
||||
std::vector<widget*> tab_order;
|
||||
|
||||
/**
|
||||
* Layouts the window.
|
||||
*
|
||||
|
@ -749,6 +752,13 @@ public:
|
|||
*/
|
||||
void remove_from_keyboard_chain(widget* widget);
|
||||
|
||||
/**
|
||||
* Add the widget to the tabbing order
|
||||
* @param widget The widget to be added to the tabbing order
|
||||
* @param at A hint for where to place the widget in the tabbing order
|
||||
*/
|
||||
void add_to_tab_order(widget* widget, int at = -1);
|
||||
|
||||
private:
|
||||
/***** ***** ***** signal handlers ***** ****** *****/
|
||||
|
||||
|
@ -771,7 +781,9 @@ private:
|
|||
|
||||
void signal_handler_sdl_key_down(const event::ui_event event,
|
||||
bool& handled,
|
||||
const SDL_Keycode key);
|
||||
const SDL_Keycode key,
|
||||
const SDL_Keymod mod,
|
||||
bool handle_tab);
|
||||
|
||||
void signal_handler_message_show_tooltip(const event::ui_event event,
|
||||
bool& handled,
|
||||
|
|
Loading…
Add table
Reference in a new issue