20 #define GETTEXT_DOMAIN "wesnoth-lib" 52 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS 70 namespace wfl {
class function_symbol_table; }
71 namespace gui2 {
class button; }
74 #define ERR_GUI LOG_STREAM(err, log_gui) 76 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__ 77 #define LOG_HEADER LOG_SCOPE_HEADER + ':' 79 #define LOG_IMPL_SCOPE_HEADER \ 80 window.get_control_type() + " [" + window.id() + "] " + __func__ 81 #define LOG_IMPL_HEADER LOG_IMPL_SCOPE_HEADER + ':' 112 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS 113 const unsigned SHOW = debug_layout_graph::SHOW;
114 const unsigned LAYOUT = debug_layout_graph::LAYOUT;
117 const unsigned SHOW = 0;
118 const unsigned LAYOUT = 0;
129 static void push_draw_event()
139 SDL_PushEvent(&event);
149 static uint32_t delay_event_callback(
const uint32_t,
void* event)
151 SDL_PushEvent(static_cast<SDL_Event*>(event));
152 delete static_cast<SDL_Event*
>(event);
165 static void delay_event(
const SDL_Event& event,
const uint32_t delay)
167 SDL_AddTimer(delay, delay_event_callback,
new SDL_Event(event));
175 static void helptip()
177 DBG_GUI_E <<
"Pushing SHOW_HELPTIP_EVENT event in queue.\n";
185 SDL_PushEvent(&event);
199 static manager& instance();
203 void remove(window& window);
205 unsigned get_id(window& window);
207 window* get_window(
const unsigned id);
219 manager& manager::instance()
221 static manager window_manager;
222 return window_manager;
225 void manager::add(window& win)
238 if(itor->second == &win) {
252 if(itor->second == &win) {
261 window* manager::get_window(
const unsigned id)
295 ,
w_(definition.width)
296 ,
h_(definition.height)
307 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS 314 manager::instance().add(*
this);
320 connect_signal<event::DRAW>(std::bind(&
window::draw,
this));
323 connect_signal<event::SDL_VIDEO_RESIZE>(std::bind(
326 connect_signal<event::SDL_ACTIVATE>(std::bind(
329 connect_signal<event::SDL_LEFT_BUTTON_UP>(
332 std::placeholders::_2,
333 std::placeholders::_3,
334 std::placeholders::_4,
337 connect_signal<event::SDL_MIDDLE_BUTTON_UP>(
340 std::placeholders::_2,
341 std::placeholders::_3,
342 std::placeholders::_4,
345 connect_signal<event::SDL_RIGHT_BUTTON_UP>(
348 std::placeholders::_2,
349 std::placeholders::_3,
350 std::placeholders::_4,
354 connect_signal<event::SDL_KEY_DOWN>(
358 connect_signal<event::SDL_KEY_DOWN>(std::bind(
361 connect_signal<event::MESSAGE_SHOW_TOOLTIP>(
364 std::placeholders::_2,
365 std::placeholders::_3,
366 std::placeholders::_5),
369 connect_signal<event::MESSAGE_SHOW_HELPTIP>(
372 std::placeholders::_2,
373 std::placeholders::_3,
374 std::placeholders::_5),
377 connect_signal<event::REQUEST_PLACEMENT>(
417 manager::instance().remove(*
this);
419 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS 421 delete debug_layout_;
428 return manager::instance().
get_window(handle);
437 }
else if(
id ==
"cancel" ||
id ==
"quit") {
491 int window::show(
const bool restore,
const unsigned auto_close_timeout)
516 if(auto_close_timeout) {
527 delay_event(event, auto_close_timeout);
534 bool mouse_button_state_initialized =
false;
542 if(!mouse_button_state_initialized) {
554 mouse_button_state_initialized =
true;
594 tb->interrupt_composition();
667 throw std::logic_error(
"The title screen is constantly changing, " 668 "which has a huge CPU usage cost. See the code comment.");
674 assert(!
item.empty());
676 const SDL_Rect dirty_rect
678 :
item.back()->get_dirty_rectangle();
684 dirty_list_.emplace_back(1,
this);
715 || (**itor).get_drawing_action()
722 (**citor).set_is_dirty(
false);
741 (**itor).draw_background(frame_buffer, 0, 0);
746 item.back()->draw_children(frame_buffer, 0, 0);
750 for(std::vector<widget*>::reverse_iterator ritor =
item.rbegin();
751 ritor !=
item.rend();
754 (**ritor).draw_foreground(frame_buffer, 0, 0);
755 (**ritor).set_is_dirty(
false);
765 assert(dirty_list_.empty());
808 const bool must_be_active)
const 825 const bool fixed_width,
826 const bool fixed_height)
828 assert(fixed_width || fixed_height);
843 ERR_GUI <<
"Unknown linked group '" <<
id <<
"'; skipping\n";
848 if(std::find(widgets.begin(), widgets.end(), wgt) == widgets.end()) {
849 widgets.push_back(wgt);
863 = std::find(widgets.begin(), widgets.end(), wgt);
865 if(itor != widgets.end()) {
868 assert(std::find(widgets.begin(), widgets.end(), wgt)
877 const auto conf = cast_config_to<window_definition>();
912 button* click_dismiss_button =
nullptr;
913 if((click_dismiss_button
914 = find_widget<button>(
this,
"click_dismiss",
false,
false))) {
919 button* btn = find_widget<button>(
this,
"ok",
false,
false);
922 click_dismiss_button = btn;
925 _(
"Click dismiss needs a 'click_dismiss' or 'ok' button."));
943 std::stringstream sstr;
944 sstr << __FILE__ <<
":" << __LINE__ <<
" in function '" << __func__
945 <<
"' found the following problem: Failed to size window;" 947 << maximum_width <<
',' << maximum_height <<
" screen size " 951 "which doesn't fit on the screen."),
957 assert(click_dismiss_button);
961 *click_dismiss_button,
972 *
this, maximum_width, maximum_height);
979 std::stringstream sstr;
980 sstr << __FILE__ <<
":" << __LINE__ <<
" in function '" << __func__
981 <<
"' found the following problem: Failed to size window;" 983 << maximum_width <<
',' << maximum_height <<
" screen size " 988 "which doesn't fit on the screen."),
999 assert(size.x >= 0 && static_cast<unsigned>(size.x) <= maximum_width
1000 && size.y >= 0 && static_cast<unsigned>(size.y) <= maximum_height);
1062 place(origin, size);
1076 point max_size(0, 0);
1084 if(size.
x > max_size.
x) {
1085 max_size.
x = size.
x;
1087 if(size.
y > max_size.
y) {
1088 max_size.
y = size.
y;
1105 size.
x = max_size.
x;
1108 size.
y = max_size.
y;
1136 void window_swap_grid(
grid*
g,
1139 const std::string&
id)
1141 assert(content_grid);
1148 grid* parent_grid =
nullptr;
1150 parent_grid = find_widget<grid>(
g,
id,
false,
false);
1153 parent_grid = find_widget<grid>(content_grid,
id,
true,
false);
1154 assert(parent_grid);
1156 if(
grid* grandparent_grid = dynamic_cast<grid*>(parent_grid->
parent())) {
1157 grandparent_grid->swap_child(
id, widget,
false);
1159 = dynamic_cast<container_base*>(parent_grid->
parent())) {
1161 c->get_grid().swap_child(
id, widget,
true);
1172 auto me = std::find(dispatchers.begin(), dispatchers.end(),
this);
1174 for(
auto it =
std::next(me); it != dispatchers.end(); ++it) {
1182 window_swap_grid(
nullptr, &
get_grid(), content_grid.
build(),
"_window_content_grid");
1185 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS 1188 const unsigned domain)
1190 debug_layout_->generate_dot_file(generator, domain);
1195 const unsigned maximum_width,
1196 const unsigned maximum_height)
1211 <<
" maximum size : " << maximum_width <<
',' 1212 << maximum_height <<
".\n";
1213 if(size.
x <= static_cast<int>(maximum_width)
1214 && size.
y <= static_cast<int>(maximum_height)) {
1220 if(size.
x > static_cast<int>(maximum_width)) {
1224 if(size.
x > static_cast<int>(maximum_width)) {
1226 <<
" Wanted width " << maximum_width
1227 <<
" resulting width " << size.
x <<
".\n";
1231 <<
" Status: Resize width succeeded.\n";
1234 if(size.
y > static_cast<int>(maximum_height)) {
1238 if(size.
y > static_cast<int>(maximum_height)) {
1240 <<
" Wanted height " << maximum_height
1241 <<
" resulting height " << size.
y <<
".\n";
1245 <<
" Status: Resize height succeeded.\n";
1248 assert(size.
x <= static_cast<int>(maximum_width)
1249 && size.
y <= static_cast<int>(maximum_height));
1258 <<
" Status: Width has been modified, rerun.\n";
1262 layout(window, maximum_width, maximum_height);
1300 if(at < 0 || at >= static_cast<int>(
tab_order.size())) {
1309 const point& new_size)
1325 const int mouse_button_mask)
1328 <<
static_cast<unsigned>(mouse_button_mask) <<
".\n";
1335 if(
const styled_widget* control = dynamic_cast<const styled_widget*>(wgt)) {
1343 const SDL_Keycode key,
1344 const SDL_Keymod mod,
1350 if(tb->is_composing()) {
1351 if(handle_tab && !
tab_order.empty() && key == SDLK_TAB) {
1352 tb->interrupt_composition();
1358 if(!
enter_disabled_ && (key == SDLK_KP_ENTER || key == SDLK_RETURN)) {
1364 }
else if(key == SDLK_SPACE) {
1366 }
else if(handle_tab && !
tab_order.empty() && key == SDLK_TAB) {
1371 if(mod & KMOD_SHIFT) {
1390 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS 1391 if(key == SDLK_F12) {
1392 debug_layout_->generate_dot_file(
"manual", debug_layout_graph::MANUAL);
1446 DBG_GUI_P <<
"Parsing window " <<
id <<
'\n';
1448 load_resolutions<resolution>(cfg);
1459 grid = std::make_shared<builder_grid>(child);
Define the common log macros for the gui toolkit.
bool click_dismiss_
Do we want to have easy close behavior?
void keyboard_capture(widget *widget)
Dialog was closed with the CANCEL button.
bool new_widgets
Do we wish to use the new library or not.
wfl::function_symbol_table functions_
The formula definitions available for the calculation formulas.
~invalidate_layout_blocker()
void remove()
Removes a tip.
Defines the exception classes for the layout algorithm.
void signal_handler_click_dismiss(const event::ui_event event, bool &handled, bool &halt, const int mouse_button_mask)
The handler for the click dismiss mouse 'event'.
virtual grid * build() const override
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
void finalize(const builder_grid &content_grid)
Finishes the initialization of the grid.
void reduce_width(const unsigned maximum_width)
Tries to reduce the width of a container.
Helper for header for the window.
typed_formula< unsigned > maximum_height_
The maximum height if automatic_placement_ is true.
bool does_click_dismiss() const
Does the window close easily?
std::function< bool(window &)> exit_hook_
const std::string message
The message to show on the helptip.
Abstract base class for text items.
void signal_handler_sdl_key_down(const event::ui_event event, bool &handled, const SDL_Keycode key, const SDL_Keymod mod, bool handle_tab)
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
typed_formula< unsigned > h_
The formula to calculate the height of the dialog.
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Key Type Default Description window_width unsigned 0 Width of the application window.
const unsigned horizontal_placement_
Sets the horizontal placement.
virtual void place(const point &origin, const point &size) override
See widget::place.
const grid & get_grid() const
A panel is a visible container to hold multiple widgets.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
Main class to show messages to the user.
void register_hotkey(const hotkey::HOTKEY_COMMAND id, const hotkey_function &function)
Registers a hotkey.
CVideo & video_
Needed so we can change what's drawn on the screen.
The window is new and not yet shown.
void show_non_modal()
Shows the window non modal.
void generate_dot_file(const std::string &, const unsigned)
Helper struct to force widgets the have the same size.
unsigned int get_rows() const
unsigned int consecutive_changed_frames_
In how many consecutive frames the window has changed.
Exception thrown when the height resizing has failed.
void draw()
Draws the window.
The message for MESSAGE_SHOW_HELPTIP.
resolution(const config &cfg)
bool is_in_dialog()
Is a dialog open?
lg::log_domain log_gui_layout("gui/layout")
void signal_handler_sdl_video_resize(const event::ui_event event, bool &handled, const point &new_size)
static CVideo & get_singleton()
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
virtual widget * build() const override
Contains the event distributor.
unsigned gamemap_width
The size of the map area, if not available equal to the screen size.
void add_to_keyboard_chain(widget *widget)
Adds the widget to the keyboard chain.
surface get_surface_portion(const surface &src, SDL_Rect &area)
Get a portion of the screen.
typed_formula< unsigned > w_
The formula to calculate the width of the dialog.
static std::string _(const char *str)
void signal_handler_message_show_tooltip(const event::ui_event event, bool &handled, const event::message &message)
Definitions for the interface to Wesnoth Markup Language (WML).
const point location
The location where to show the helptip.
surface & getSurface()
Returns a reference to the framebuffer.
int mouse_button_state_
The state of the mouse button.
void get_screen_size_variables(wfl::map_formula_callable &variable)
Gets a formula object with the screen size.
void init_mouse_location()
Initializes the location of the mouse.
int width
The current width of all widgets in the group, -1 if the width is not linked.
The message callbacks hold a reference to a message.
#define CLOSE_WINDOW_EVENT
static bool is_active(const widget *wgt)
The event handler class for the widget library.
void connect()
Connects the dispatcher to the event handler.
static std::string at(const std::string &file, int line)
status status_
The status of the window.
void reduce_height(const unsigned maximum_height)
Tries to reduce the height of a container.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
std::vector< widget * > widgets
The widgets linked.
surface restorer_
When the window closes this surface is used to undraw the window.
Exception thrown when the width has been modified during resizing.
The dialog was closed automatically as its timeout had been reached.
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
bool suspend_drawing_
Avoid drawing the window.
This file contains the settings handling of the widget library.
bool enter_disabled_
Disable the enter key see our setter for more info.
const SDL_Rect source_rect
The size of the entity requesting to show a helptip.
bool invalidate_layout_blocked_
Is invalidate_layout blocked, see invalidate_layout_blocker.
bool need_layout_
When set the form needs a full layout redraw cycle.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button click.
void signal_handler_close_window()
typed_formula< bool > reevaluate_best_size_
The formula to determine whether the size is good.
builder_window::window_resolution::tooltip_info helptip_
The settings for the helptip.
bool is_toplevel_
Whether the window has other windows behind it.
std::vector< dispatcher * > & get_all_dispatchers()
Gets all event dispatchers in the Z order.
static const unsigned HORIZONTAL_ALIGN_RIGHT
static thread_local std::deque< std::string > call_stack
For printing error messages when WFL parsing or evaluation fails, this contains the names of the WFL ...
The window is being shown.
This file contains the definitions for the gui2::event::message class.
unsigned int get_cols() const
typed_formula< unsigned > y_
The formula to calculate the y value of the dialog.
Exception thrown when the width resizing has failed.
Basic template class to generate new items.
#define log_scope2(domain, description)
const bool automatic_placement_
Do we wish to place the widget automatically?
typed_formula< unsigned > maximum_width_
The maximum width if automatic_placement_ is true.
void init_linked_size_group(const std::string &id, const bool fixed_width, const bool fixed_height)
Initializes a linked size group.
typed_formula< unsigned > x_
The formula to calculate the x value of the dialog.
std::vector< std::vector< widget * > > dirty_list_
The list with dirty items in the window.
void set_mouse_behavior(const mouse_behavior mouse_behavior)
bool escape_disabled_
Disable the escape key see our setter for more info.
The window has been requested to be closed but still needs to evaluate the request.
static window * window_instance(const unsigned handle)
Returns the instance of a window.
void add_linked_widget(const std::string &id, widget *widget)
Adds a widget to a linked size group.
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Helper class, don't construct this directly.
static const unsigned VERTICAL_ALIGN_TOP
void remove_from_keyboard_chain(widget *widget)
Remove the widget from the keyboard chain.
invalidate_layout_blocker(window &window)
int show(const bool restore=true, const unsigned auto_close_timeout=0)
Shows the window.
Default, unset return value.
#define SHOW_HELPTIP_EVENT
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
const unsigned vertical_placement_
Sets the vertical placement.
void undraw_floating_labels(surface screen)
std::vector< widget * > tab_order
List of widgets in the tabbing order.
static const unsigned VERTICAL_ALIGN_CENTER
bool has_linked_size_group(const std::string &id)
Is the linked size group defined for this window?
bool click_dismiss(const int mouse_button_mask)
Handles a mouse click event for dismissing the dialog.
static const unsigned HORIZONTAL_ALIGN_CENTER
unsigned screen_width
The screen resolution and pixel pitch should be available for all widgets since their drawing method ...
The window has been closed.
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
lg::log_domain log_gui_draw("gui/draw")
A generic container base class.
void signal_handler_request_placement(const event::ui_event event, bool &handled)
builder_window::window_resolution::tooltip_info tooltip_
The settings for the tooltip.
show_mode show_mode_
The mode in which the window is shown.
static void layout(window &window, const unsigned maximum_width, const unsigned maximum_height)
Layouts the window.
window_definition(const config &cfg)
static const unsigned VERTICAL_ALIGN_BOTTOM
static retval get_retval_by_id(const std::string &id)
Gets the retval for the default buttons.
point get_mouse_position()
Returns the current mouse position.
void undraw()
Undraws the window.
Contains the SDL_Rect helper code.
void remove_child(const unsigned row, const unsigned col)
Removes and frees a widget in a cell.
void show_tooltip()
Shows the window as a tooltip.
void mouse_capture(const bool capture=true)
bool disable_click_dismiss() const override
See widget::disable_click_dismiss.
bool restore_
Whether the window should undraw the window using restorer_.
void redraw_windows_on_top() const
Schedules windows on top of us (if any) to redraw.
void layout()
Layouts the window.
std::unique_ptr< event::distributor > event_distributor_
void signal_handler_message_show_helptip(const event::ui_event event, bool &handled, const event::message &message)
void invalidate_layout()
Updates the size of the window.
friend class debug_layout_graph
dialogs::modal_dialog * owner_
The dialog that owns the window.
retval
Default window/dialog return values.
virtual void layout_children() override
See widget::layout_children.
static const unsigned HORIZONTAL_ALIGN_LEFT
std::unique_ptr< window > build(const builder_window::window_resolution &definition)
Builds a window.
Dialog was closed with the OK button.
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
void remove_linked_widget(const std::string &id, const widget *widget)
Removes a widget from a linked size group.
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
int height
The current height of all widgets in the group, -1 if the height is not linked.
A config object defines a single node in a WML file, with access to child nodes.
void add_to_tab_order(widget *widget, int at=-1)
Add the widget to the tabbing order.
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
void set_want_keyboard_input(const bool want_keyboard_input)
std::shared_ptr< halo_record > handle
base class of top level items, the only item which needs to store the final canvases to draw on...
std::map< std::string, linked_size > linked_size_
List of the widgets, whose size are linked together.
wfl::map_formula_callable variables_
The variables of the canvas.
std::string::const_iterator iterator
void initialize_state()
Initializes the state of the keyboard and mouse.
HOTKEY_COMMAND get_id(const std::string &command)
returns get_hotkey_command(command).id
builder_window(const config &cfg)
Contains the implementation details for lexical_cast and shouldn't be used directly.
void draw_floating_labels(surface screen)
ui_event
The event send to the dispatcher.
void layout_linked_widgets()
Layouts the linked widgets.
std::pair< std::string, unsigned > item
void show(const std::string &window_id, const t_string &message, const point &mouse, const SDL_Rect &source_rect)
Shows a tip.
std::function< void()> callback_next_draw_
Basic exception when the layout doesn't fit.