The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
widget.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2007 - 2025
3 by Mark de Wever <koraq@xs4all.nl>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#define GETTEXT_DOMAIN "wesnoth-lib"
17
18#include "draw.hpp"
19#include "draw_manager.hpp"
20#include "gui/widgets/grid.hpp"
24#include "gui/core/log.hpp"
26#include "sdl/rect.hpp"
27
28namespace gui2
29{
30
31/***** ***** ***** Constructor and destructor. ***** ***** *****/
32
34 : enable_lua_ptr<widget>(this)
35 , id_("")
36 , parent_(nullptr)
37 , x_(-1)
38 , y_(-1)
39 , width_(0)
40 , height_(0)
41 , layout_size_()
42#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
43 , last_best_size_()
44#endif
45 , linked_group_()
46 , visible_(visibility::visible)
47 , redraw_action_(redraw_action::full)
48 , clipping_rectangle_()
49 , debug_border_mode_(debug_border::none)
50 , debug_border_color_(0,0,0,0)
51{
52 DBG_GUI_LF << "widget create: " << static_cast<void*>(this);
53}
54
56 : enable_lua_ptr<widget>(this)
57 , id_(builder.id)
58 , parent_(nullptr)
59 , x_(-1)
60 , y_(-1)
61 , width_(0)
62 , height_(0)
63 , layout_size_()
64#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
65 , last_best_size_()
66#endif
67 , linked_group_(builder.linked_group)
68 , visible_(visibility::visible)
69 , redraw_action_(redraw_action::full)
70 , clipping_rectangle_()
71 , debug_border_mode_(builder.debug_border_mode)
72 , debug_border_color_(builder.debug_border_color)
73{
74 DBG_GUI_LF << "widget create: " << static_cast<void*>(this);
75}
76
78{
80 << "widget destroy: " << static_cast<void*>(this)
81 << " (id: " << id_ << ')';
82
83 widget* p = parent();
84 while(p) {
85 fire(event::NOTIFY_REMOVAL, *p, nullptr);
86 p = p->parent();
87 }
88
89 if(!linked_group_.empty()) {
90 if(window* window = get_window()) {
92 }
93 }
94}
95
96/***** ***** ***** ***** ID functions. ***** ***** ***** *****/
97
98void widget::set_id(const std::string& id)
99{
100 styled_widget* this_ctrl = dynamic_cast<styled_widget*>(this);
101
103 << "set id of " << static_cast<void*>(this) << " to '" << id << "' "
104 << "(was '" << id_ << "'). Widget type: "
105 << (this_ctrl ? this_ctrl->get_control_type() : typeid(widget).name());
106
107 id_ = id;
108}
109
110const std::string& widget::id() const
111{
112 return id_;
113}
114
115/***** ***** ***** ***** Parent functions ***** ***** ***** *****/
116
118{
119 // Go up into the parent tree until we find the top level
120 // parent, we can also be the toplevel so start with
121 // ourselves instead of our parent.
122 widget* result = this;
123 while(result->parent_) {
124 result = result->parent_;
125 }
126
127 // on error dynamic_cast returns nullptr which is what we want.
128 return dynamic_cast<window*>(result);
129}
130
132{
133 // Go up into the parent tree until we find the top level
134 // parent, we can also be the toplevel so start with
135 // ourselves instead of our parent.
136 const widget* result = this;
137 while(result->parent_) {
138 result = result->parent_;
139 }
140
141 // on error dynamic_cast returns nullptr which is what we want.
142 return dynamic_cast<const window*>(result);
143}
144
146{
147 widget* result = parent_;
148 while(result && dynamic_cast<grid*>(result) == nullptr) {
149 result = result->parent_;
150 }
151
152 return result ? dynamic_cast<grid*>(result) : nullptr;
153}
154
156{
157 const widget* result = parent_;
158 while(result && dynamic_cast<const grid*>(result) == nullptr) {
159 result = result->parent_;
160 }
161
162 return result ? dynamic_cast<const grid*>(result) : nullptr;
163}
164
166{
167 parent_ = parent;
168}
169
171{
172 return parent_;
173}
174
175/***** ***** ***** ***** Size and layout functions. ***** ***** ***** *****/
176
177void widget::layout_initialize(const bool /*full_initialization*/)
178{
180 assert(get_window());
181
183 if(!linked_group_.empty()) {
185 }
186}
187
188void widget::demand_reduce_width(const unsigned /*maximum_width*/)
189{
190 /* DO NOTHING */
191}
192
193void widget::request_reduce_height(const unsigned /*maximum_height*/)
194{
195 /* DO NOTHING */
196}
197
198void widget::demand_reduce_height(const unsigned /*maximum_height*/)
199{
200 /* DO NOTHING */
201}
202
204{
206
207 point result = layout_size_;
208 if(result == point()) {
209 result = calculate_best_size();
210 //Adjust to linked widget size if linked widget size was already calculated.
211 if (get_window() && !get_window()->get_need_layout() && !linked_group_.empty()) {
213 result.x = std::max(result.x, linked_size.x);
214 result.y = std::max(result.y, linked_size.y);
215 }
216 }
217
218#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
219 last_best_size_ = result;
220#endif
221
222 return result;
223}
224
226{
227 return false;
228}
229
230void widget::set_origin(const point& origin)
231{
232 x_ = origin.x;
233 y_ = origin.y;
234}
235
236void widget::set_size(const point& size)
237{
238 assert(size.x >= 0);
239 assert(size.y >= 0);
240
241 queue_redraw();
242 width_ = size.x;
243 height_ = size.y;
244
245 queue_redraw();
246}
247
248void widget::place(const point& origin, const point& size)
249{
250 assert(size.x >= 0);
251 assert(size.y >= 0);
252
253 queue_redraw();
254 x_ = origin.x;
255 y_ = origin.y;
256 width_ = size.x;
257 height_ = size.y;
258
259#if 0
261 << "Id " << id()
262 << " rect " << get_rectangle()
263 << " parent "
264 << (parent ? parent->get_x() : 0)
265 << ','
266 << (parent ? parent->get_y() : 0)
267 << " screen origin " << x_ << ',' << y_
268 << ".\n";
269#endif
270
271 queue_redraw();
272}
273
274void widget::move(const int x_offset, const int y_offset)
275{
276 x_ += x_offset;
277 y_ += y_offset;
278}
279
280void widget::set_horizontal_alignment(const std::string& alignment)
281{
282 grid* parent_grid = get_parent_grid();
283 if(!parent_grid) {
284 return;
285 }
286
288
289 // TODO: evaluate necessity
290 //get_window()->invalidate_layout();
291}
292
293void widget::set_vertical_alignment(const std::string& alignment)
294{
295 grid* parent_grid = get_parent_grid();
296 if(!parent_grid) {
297 return;
298 }
299
301
302 // TODO: evaluate necessity
303 //get_window()->invalidate_layout();
304}
305
307{
308 /* DO NOTHING */
309}
310
312{
313 return point(x_, y_);
314}
315
317{
318 return point(width_, height_);
319}
320
322{
323 return {get_origin(), get_size()};
324}
325
326int widget::get_x() const
327{
328 return x_;
329}
330
331int widget::get_y() const
332{
333 return y_;
334}
335
336unsigned widget::get_width() const
337{
338 return width_;
339}
340
341unsigned widget::get_height() const
342{
343 return height_;
344}
345
347{
348 layout_size_ = size;
349}
350
352{
353 return layout_size_;
354}
355
356void widget::set_linked_group(const std::string& linked_group)
357{
358 linked_group_ = linked_group;
359}
360
361/***** ***** ***** ***** Drawing functions. ***** ***** ***** *****/
362
367
369{
370 switch(get_drawing_action()) {
372 return {};
374 return clipping_rectangle_;
376 default:
377 return get_rectangle();
378 }
379}
380
382{
383 assert(visible_ == visibility::visible);
384
386 return true;
387 }
388
389 // Set viewport and clip so we can draw in local coordinates.
392 // Presumably we are drawing to our window's render buffer.
393 point window_origin = get_window()->get_origin();
394 dest.shift(-window_origin);
395 auto view_setter = draw::set_viewport(dest);
396 clip.shift(-get_origin());
397 auto clip_setter = draw::reduce_clip(clip);
398
399 return impl_draw_background();
400}
401
403{
404 assert(visible_ == visibility::visible);
405
407 return;
408 }
409
410 // Set viewport and clip so we can draw in local coordinates.
413 // Presumably we are drawing to our window's render buffer.
414 point window_origin = get_window()->get_origin();
415 dest.shift(-window_origin);
416 auto view_setter = draw::set_viewport(dest);
417 clip.shift(-get_origin());
418 auto clip_setter = draw::reduce_clip(clip);
419
421}
422
424{
425 assert(visible_ == visibility::visible);
426
428 return true;
429 }
430
431 // Set viewport and clip so we can draw in local coordinates.
434 // Presumably we are drawing to our window's render buffer.
435 point window_origin = get_window()->get_origin();
436 dest.shift(-window_origin);
437 auto view_setter = draw::set_viewport(dest);
438 clip.shift(-get_origin());
439 auto clip_setter = draw::reduce_clip(clip);
440
442 return impl_draw_foreground();
443}
444
450
463
465{
466 if (!width_ && !height_) {
467 // Do nothing if the widget hasn't yet been placed.
468 return;
469 }
471}
472
473void widget::queue_redraw(const rect& region)
474{
475 get_window()->queue_rerender(region);
477}
478
480{
481 if(visible == visible_) {
482 return;
483 }
484
485 // Switching to or from invisible should invalidate the layout
486 // if the widget has already been laid out.
487 const bool need_resize = visible_ == visibility::invisible
490
491 if(need_resize) {
495 } else {
497 if(window) {
499 }
500 }
501 } else {
502 queue_redraw();
503 }
504}
505
507{
508 return visible_;
509}
510
516
517void widget::set_debug_border_mode(const debug_border debug_border_mode)
518{
519 debug_border_mode_ = debug_border_mode;
520}
521
522void widget::set_debug_border_color(const color_t debug_border_color)
523{
524 debug_border_color_ = debug_border_color;
525}
526
528{
529 switch(debug_border_mode_) {
531 /* DO NOTHING */
532 break;
533
536 break;
537
540 break;
541
542 default:
543 assert(false);
544 }
545}
546
547/***** ***** ***** ***** Query functions ***** ***** ***** *****/
548
549widget* widget::find_at(const point& coordinate, const bool must_be_active)
550{
551 return is_at(coordinate, must_be_active) ? this : nullptr;
552}
553
554const widget* widget::find_at(const point& coordinate,
555 const bool must_be_active) const
556{
557 return is_at(coordinate, must_be_active) ? this : nullptr;
558}
559
560widget* widget::find(const std::string_view id, const bool /*must_be_active*/)
561{
562 return id_ == id ? this : nullptr;
563}
564
565const widget* widget::find(const std::string_view id, const bool /*must_be_active*/) const
566{
567 return id_ == id ? this : nullptr;
568}
569
571{
572 return &widget == this;
573}
574
575bool widget::is_at(const point& coordinate) const
576{
577 return is_at(coordinate, true);
578}
579
580bool widget::recursive_is_visible(const widget* widget, const bool must_be_active) const
581{
582 while(widget) {
584 || (widget->visible_ == visibility::hidden && must_be_active)) {
585 return false;
586 }
587
589 }
590
591 return true;
592}
593
594bool widget::is_at(const point& coordinate, const bool must_be_active) const
595{
596 if(!recursive_is_visible(this, must_be_active)) {
597 return false;
598 }
599
600 return get_rectangle().contains(coordinate);
601}
602
603} // namespace gui2
Allows creation of lua_ptr<T> instances, but does not affect the lifetime of the T itself.
Definition lua_ptr.hpp:34
Main class to show messages to the user.
Definition message.hpp:36
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Base container class.
Definition grid.hpp:32
static const unsigned HORIZONTAL_MASK
Definition grid.hpp:60
void set_child_alignment(widget *widget, unsigned set_flag, unsigned mode_mask)
Modifies the widget alignment data of a child cell containing a specific widget.
Definition grid.cpp:931
static const unsigned VERTICAL_MASK
Definition grid.hpp:53
virtual const std::string & get_control_type() const =0
Returns the type of this styled_widget.
Base class for all widgets.
Definition widget.hpp:55
const point & layout_size() const
Definition widget.cpp:351
virtual void demand_reduce_width(const unsigned maximum_width)
Tries to reduce the width of a widget.
Definition widget.cpp:188
void set_layout_size(const point &size)
Definition widget.cpp:346
grid * get_parent_grid()
Get the parent grid.
Definition widget.cpp:145
redraw_action redraw_action_
Field for the action to do on a drawing request.
Definition widget.hpp:655
bool draw_foreground()
Draws the foreground of the widget.
Definition widget.cpp:423
virtual void set_visible_rectangle(const rect &rectangle)
Sets the visible rectangle for a widget.
Definition widget.cpp:451
point get_best_size() const
Gets the best size for the widget.
Definition widget.cpp:203
virtual void place(const point &origin, const point &size)
Places the widget.
Definition widget.cpp:248
debug_border debug_border_mode_
Mode for drawing the debug border.
Definition widget.hpp:666
void set_visible(const visibility visible)
Definition widget.cpp:479
void set_id(const std::string &id)
Definition widget.cpp:98
int x_
The x-coordinate of the widget on the screen.
Definition widget.hpp:473
virtual void demand_reduce_height(const unsigned maximum_height)
Tries to reduce the height of a widget.
Definition widget.cpp:198
virtual void layout_children()
Allows a widget to update its children.
Definition widget.cpp:306
visibility visible_
Field for the status of the visibility.
Definition widget.hpp:652
virtual ~widget() override
Definition widget.cpp:77
rect clipping_rectangle_
The clipping rectangle if a widget is partly visible.
Definition widget.hpp:658
virtual void layout_initialize(const bool full_initialization)
How the layout engine works.
Definition widget.cpp:177
void set_linked_group(const std::string &linked_group)
Definition widget.cpp:356
void queue_redraw()
Indicates that this widget should be redrawn.
Definition widget.cpp:464
widget * parent_
The parent widget.
Definition widget.hpp:217
visibility get_visible() const
Definition widget.cpp:506
point get_origin() const
Returns the screen origin of the widget.
Definition widget.cpp:311
color_t debug_border_color_
The color for the debug border.
Definition widget.hpp:669
int get_x() const
Definition widget.cpp:326
virtual bool impl_draw_foreground()
See draw_foreground.
Definition widget.hpp:589
virtual widget * find(const std::string_view id, const bool must_be_active)
Returns a widget with the wanted id.
Definition widget.cpp:560
unsigned width_
The width of the widget.
Definition widget.hpp:479
unsigned get_width() const
Definition widget.cpp:336
int get_y() const
Definition widget.cpp:331
void set_parent(widget *parent)
Definition widget.cpp:165
virtual point calculate_best_size() const =0
Calculates the best size.
rect get_dirty_rectangle() const
Gets the dirty rectangle of the widget.
Definition widget.cpp:445
point get_size() const
Returns the size of the widget.
Definition widget.cpp:316
void draw_children()
Draws the children of a widget.
Definition widget.cpp:402
virtual void move(const int x_offset, const int y_offset)
Moves a widget.
Definition widget.cpp:274
bool draw_background()
Draws the background of a widget.
Definition widget.cpp:381
rect calculate_blitting_rectangle() const
Calculates the blitting rectangle of the widget.
Definition widget.cpp:363
virtual bool has_widget(const widget &widget) const
Does the widget contain the widget.
Definition widget.cpp:570
virtual void set_origin(const point &origin)
Sets the origin of the widget.
Definition widget.cpp:230
unsigned get_height() const
Definition widget.cpp:341
const std::string & id() const
Definition widget.cpp:110
window * get_window()
Get the parent window.
Definition widget.cpp:117
bool recursive_is_visible(const widget *widget, const bool must_be_active) const
Is the widget and every single one of its parents visible?
Definition widget.cpp:580
virtual bool impl_draw_background()
See draw_background.
Definition widget.hpp:578
int y_
The y-coordinate of the widget on the screen.
Definition widget.hpp:476
virtual void set_horizontal_alignment(const std::string &alignment)
Sets the horizontal alignment of the widget within its parent grid.
Definition widget.cpp:280
std::string id_
The id is the unique name of the widget in a certain context.
Definition widget.hpp:177
visibility
Visibility settings done by the user.
Definition widget.hpp:65
@ visible
The user sets the widget visible, that means:
@ invisible
The user set the widget invisible, that means:
@ hidden
The user sets the widget hidden, that means:
std::string linked_group_
The linked group the widget belongs to.
Definition widget.hpp:518
void set_debug_border_mode(const debug_border debug_border_mode)
Definition widget.cpp:517
rect calculate_clipping_rectangle() const
Calculates the clipping rectangle of the widget.
Definition widget.cpp:368
redraw_action get_drawing_action() const
Definition widget.cpp:511
rect get_rectangle() const
Gets the bounding rectangle of the widget on the screen.
Definition widget.cpp:321
virtual void impl_draw_children()
See draw_children.
Definition widget.hpp:584
void draw_debug_border()
Definition widget.cpp:527
point layout_size_
The best size for the widget.
Definition widget.hpp:494
@ outline
Single-pixel outline.
@ fill
Flood-filled rectangle.
virtual widget * find_at(const point &coordinate, const bool must_be_active)
Returns the widget at the wanted coordinates.
Definition widget.cpp:549
void set_debug_border_color(const color_t debug_border_color)
Definition widget.cpp:522
unsigned height_
The height of the widget.
Definition widget.hpp:482
virtual void set_size(const point &size)
Sets the size of the widget.
Definition widget.cpp:236
virtual void request_reduce_height(const unsigned maximum_height)
Tries to reduce the height of a widget.
Definition widget.cpp:193
virtual bool can_wrap() const
Can the widget wrap.
Definition widget.cpp:225
virtual bool is_at(const point &coordinate) const override
See event::dispatcher::is_at.
Definition widget.cpp:575
redraw_action
Visibility set by the engine.
Definition widget.hpp:103
@ none
The widget is not visible.
@ partly
The widget is partly visible.
@ full
The widget is fully visible.
widget * parent()
Definition widget.cpp:170
virtual void set_vertical_alignment(const std::string &alignment)
Sets the horizontal alignment of the widget within its parent grid.
Definition widget.cpp:293
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition window.hpp:59
void invalidate_layout()
Updates the size of the window.
Definition window.cpp:759
point get_linked_size(std::string_view group_id) const
Definition window.hpp:415
void add_linked_widget(const std::string &id, widget *widget)
Adds a widget to a linked size group.
Definition window.cpp:799
void remove_linked_widget(const std::string &id, const widget *widget)
Removes a widget from a linked size group.
Definition window.cpp:813
void queue_rerender(const rect &region)
Queue a rerender of the internal render buffer.
Definition window.cpp:675
This file contains the definitions for the gui2::event::message class.
Drawing functions, for drawing things on the screen.
Define the common log macros for the gui toolkit.
#define DBG_GUI_LF
Definition log.hpp:62
std::string id
Text to match against addon_info.tags()
Definition manager.cpp:199
This file contains the window object, this object is a top level container which has the event manage...
#define PLAIN_LOG
Definition log.hpp:296
void invalidate_region(const rect &region)
Mark a region of the screen as requiring redraw.
void rect(const ::rect &rect)
Draw a rectangle.
Definition draw.cpp:171
clip_setter reduce_clip(const ::rect &clip)
Set the clipping area to the intersection of the current clipping area and the given rectangle.
Definition draw.cpp:595
void fill()
Definition draw.cpp:115
viewport_setter set_viewport(const ::rect &viewport)
Set the viewport.
Definition draw.cpp:689
@ REQUEST_PLACEMENT
Definition handler.hpp:182
unsigned get_v_align(const std::string &v_align)
Returns the vertical alignment.
Definition helper.cpp:38
unsigned get_h_align(const std::string &h_align)
Returns the horizontal alignment.
Definition helper.cpp:53
Generic file dialog.
bool new_widgets
Do we wish to use the new library or not.
Definition settings.cpp:23
Contains the SDL_Rect helper code.
This file contains the settings handling of the widget library.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition color.hpp:51
Contains the info needed to instantiate a widget.
The message callbacks hold a reference to a message.
Definition message.hpp:46
Holds a 2D point.
Definition point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition rect.hpp:49
bool empty() const
False if both w and h are > 0, true otherwise.
Definition rect.cpp:49
bool contains(int x, int y) const
Whether the given point lies within the rectangle.
Definition rect.cpp:54
rect intersect(const rect &r) const
Calculates the intersection of this rectangle and another; that is, the maximal rectangle that is con...
Definition rect.cpp:92
void shift(const point &p)
Shift the rectangle by the given relative position.
Definition rect.cpp:106
mock_party p