From ed27b67f1e645f90f918c3f028cb0b8655dfd83f Mon Sep 17 00:00:00 2001 From: Charles Dang Date: Fri, 23 Jun 2017 13:20:50 +1100 Subject: [PATCH] Port floating textbox/command console to GUI2 The old floating textbox was extremely entwined with the controller_base, play_controller, and menu_handler classes. controller_base::have_keyboard_focus essentially controlled whether some events were executed based on whether the floating textbox was open or not. Additionally, those events weren't even reached if a UI dialog was open at all. The new design features a singleton console class that can be called from anywhere, not just the game. I've also decoupled the execution object from play_controller. The relevant functions in menu_handler are now passed to the console as callbacks. To work around map events such as clicking not being available if the console was open, I removed the exclusionary is-in-dialog check from controller_base::handle_event and instead exit early out certain types of events using controller_base::have_keyboard_focus. As mentioned in the accompanying comment, this isn't the best solution, but it will do for now. The new console also isn't fully feature-comparable with the old GUI1 one. The following are still missing: * The checkbox, for use when sending messages. * Tab completion. * A crash occurs when existing the app if a game was exited with the console open. I'm leaving the old floating_textbox code around for now for reference. --- data/gui/window/command_console.cfg | 120 ++++++++++++++++++++++++++++ projectfiles/CodeBlocks/wesnoth.cbp | 2 + source_lists/wesnoth | 1 + src/controller_base.cpp | 16 +++- src/gui/dialogs/command_console.cpp | 89 +++++++++++++++++++++ src/gui/dialogs/command_console.hpp | 102 +++++++++++++++++++++++ src/menu_events.cpp | 42 ++++++---- src/menu_events.hpp | 8 +- src/play_controller.cpp | 53 +----------- src/play_controller.hpp | 7 +- src/playsingle_controller.cpp | 1 - src/playsingle_controller.hpp | 1 - 12 files changed, 362 insertions(+), 80 deletions(-) create mode 100644 data/gui/window/command_console.cfg create mode 100644 src/gui/dialogs/command_console.cpp create mode 100644 src/gui/dialogs/command_console.hpp diff --git a/data/gui/window/command_console.cfg b/data/gui/window/command_console.cfg new file mode 100644 index 00000000000..7a55d20091a --- /dev/null +++ b/data/gui/window/command_console.cfg @@ -0,0 +1,120 @@ +#textdomain wesnoth-lib + +[window_definition] + id = "command_console_window" + description = "The window definition for the command console." + + [resolution] + + # NOTE: we don't specify borders like most definitions since we want + # widgets to fully reach the edge of the window. + + [background] + + [draw] + + [rectangle] + x = 0 + y = 0 + w = "(width)" + h = "(height)" + + fill_color = "0, 0, 0, 150" + [/rectangle] + + [/draw] + + [/background] + + [foreground] + + [draw] + + [/draw] + + [/foreground] + + [/resolution] + +[/window_definition] + +# +# TODO: improve visual design. Hard to see! +# + +[window] + id = "command_console" + description = "Command console" + + [resolution] + definition = "command_console_window" + + automatic_placement = false + + x = 0 + y = "(gamemap_height - 25)" + + width = "(gamemap_width)" + height = "25" + + [tooltip] + id = "tooltip_large" + [/tooltip] + + [helptip] + id = "tooltip_large" + [/helptip] + + [grid] + + [row] + grow_factor = 0 + + [column] + grow_factor = 0 + border = "left,right" + border_size = 5 + horizontal_alignment = "left" + + [label] + id = "prompt" + definition = "default_small" + use_markup = true + [/label] + + [/column] + + [column] + grow_factor = 1 + border = "left,right" + border_size = 5 + horizontal_grow = true + + [text_box] + id = "input" + definition = "transparent" + [/text_box] + + [/column] + + # TODO! + [column] + grow_factor = 0 + border = "left,right" + border_size = 5 + + [toggle_button] + id = "toggle" + definition = "default" + label = "Implement Me!" + [/toggle_button] + + [/column] + + [/row] + + [/grid] + + [/resolution] + +[/window] diff --git a/projectfiles/CodeBlocks/wesnoth.cbp b/projectfiles/CodeBlocks/wesnoth.cbp index f205807aeb5..bf094e21261 100644 --- a/projectfiles/CodeBlocks/wesnoth.cbp +++ b/projectfiles/CodeBlocks/wesnoth.cbp @@ -546,6 +546,8 @@ + + diff --git a/source_lists/wesnoth b/source_lists/wesnoth index 9e5e45395bd..3ed71878f47 100644 --- a/source_lists/wesnoth +++ b/source_lists/wesnoth @@ -170,6 +170,7 @@ gui/dialogs/attack_predictions.cpp gui/dialogs/campaign_difficulty.cpp gui/dialogs/campaign_selection.cpp gui/dialogs/chat_log.cpp +gui/dialogs/command_console.cpp gui/dialogs/core_selection.cpp gui/dialogs/debug_clock.cpp gui/dialogs/depcheck_confirm_change.cpp diff --git a/src/controller_base.cpp b/src/controller_base.cpp index 931b2a123a2..263d651e50c 100644 --- a/src/controller_base.cpp +++ b/src/controller_base.cpp @@ -17,6 +17,7 @@ #include "display.hpp" #include "events.hpp" +#include "gui/dialogs/loading_screen.hpp" #include "hotkey/command_executor.hpp" #include "hotkey/hotkey_command.hpp" #include "log.hpp" @@ -26,6 +27,7 @@ #include "scripting/plugins/context.hpp" #include "show_dialog.hpp" //gui::in_dialog #include "soundsource.hpp" + static lg::log_domain log_display("display"); #define ERR_DP LOG_STREAM(err, log_display) @@ -49,7 +51,17 @@ controller_base::~controller_base() void controller_base::handle_event(const SDL_Event& event) { - if(gui::in_dialog()) { + /* TODO: since GUI2 and the main game are now part of the same event context, there is some conflict + * between the GUI2 and event handlers such as these. By design, the GUI2 sdl handler is always on top + * of the handler queue, so its events are handled last. This means events here have a chance to fire + * first. have_keyboard_focus currently returns false if a dialog open, but this is just as stopgap + * measure. We need to figure out a better way to filter out events. + */ + //if(gui::in_dialog()) { + // return; + //} + + if(gui2::dialogs::loading_screen::displaying()) { return; } @@ -152,7 +164,7 @@ void controller_base::keyup_listener::handle_event(const SDL_Event& event) bool controller_base::have_keyboard_focus() { - return true; + return !gui::in_dialog(); } bool controller_base::handle_scroll(int mousex, int mousey, int mouse_flags, double x_axis, double y_axis) diff --git a/src/gui/dialogs/command_console.cpp b/src/gui/dialogs/command_console.cpp new file mode 100644 index 00000000000..f6644dc3736 --- /dev/null +++ b/src/gui/dialogs/command_console.cpp @@ -0,0 +1,89 @@ +/* + Copyright (C) 2017 by the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#define GETTEXT_DOMAIN "wesnoth-lib" + +#include "gui/dialogs/command_console.hpp" + +#include "gui/auxiliary/find_widget.hpp" +#include "gui/dialogs/modal_dialog.hpp" +#include "gui/widgets/label.hpp" +#include "gui/widgets/settings.hpp" +#include "gui/widgets/text_box.hpp" +#include "gui/widgets/window.hpp" + +namespace gui2 +{ +namespace dialogs +{ +REGISTER_DIALOG(command_console) + +std::unique_ptr command_console::singleton_ = nullptr; + +command_console::command_console(const std::string& prompt, callback_t callback) + : input_(nullptr) + , prompt_(prompt) + , command_callback_(callback) +{ +} + +void command_console::post_build(window& window) +{ + // Allow ESC to dismiss the console. + connect_signal_pre_key_press(window, + std::bind(&command_console::window_key_press_callback, this, _5)); + + input_ = find_widget(&window, "input", false, true); + + // Execute provided callback on ENTER press. + connect_signal_pre_key_press(*input_, + std::bind(&command_console::input_key_press_callback, this, _5)); +} + +void command_console::pre_show(window& window) +{ + find_widget