The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
styled_widget.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 - 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#pragma once
17
18#include "font/text.hpp"
19#include "gui/core/canvas.hpp"
23
24namespace gui2
25{
26
27// ------------ WIDGET -----------{
28
29namespace implementation
30{
31struct builder_styled_widget;
32} // namespace implementation
33
34class styled_widget : public widget
35{
36 friend class debug_layout_graph;
37
38public:
39 /**
40 * Constructor.
41 *
42 * @param builder The builder object with the settings for the object.
43 * @param control_type The type of control to be built.
44 */
46 const std::string& control_type);
47
48 /**
49 * Sets the members of the styled_widget.
50 *
51 * The map contains named members it can set, controls inheriting from us
52 * can add additional members to set by this function. The following
53 * members can by the following key:
54 * * label_ label
55 * * tooltip_ tooltip
56 * * help_message_ help
57 *
58 *
59 * @param data Map with the key value pairs to set the
60 * members.
61 */
62 virtual void set_members(const widget_item& data);
63
64 /***** ***** ***** ***** State handling ***** ***** ***** *****/
65
66 /**
67 * Sets the styled_widget's state.
68 *
69 * Sets the styled_widget in the active state, when inactive a styled_widget can't be
70 * used and doesn't react to events. (Note read-only for a text_box_base is a
71 * different state.)
72 */
73 virtual void set_active(const bool active) = 0;
74
75 /** Gets the active state of the styled_widget. */
76 virtual bool get_active() const = 0;
77
78protected:
79 /** Returns the id of the state.
80 *
81 * The current state is also the index canvases_.
82 */
83 virtual unsigned get_state() const = 0;
84
85public:
86 /***** ***** ***** ***** Easy close handling ***** ***** ***** *****/
87
88 /**
89 * See @ref widget::disable_click_dismiss.
90 *
91 * The default behavior is that a widget blocks easy close, if not it
92 * should override this function.
93 */
94 bool disable_click_dismiss() const override;
95
96 /** See @ref widget::create_walker. */
97 virtual iteration::walker_ptr create_walker() override;
98
99 /***** ***** ***** ***** layout functions ***** ***** ***** *****/
100
101 /**
102 * Gets the minimum size as defined in the config.
103 *
104 * @pre config_ != nullptr
105 *
106 * @returns The size.
107 */
109
110 /**
111 * Gets the default size as defined in the config.
112 *
113 * @pre config_ != nullptr
114 *
115 * @returns The size.
116 */
118
119 /**
120 * Gets the best size as defined in the config.
121 *
122 * @pre config_ != nullptr
123 *
124 * @returns The size.
125 */
127
128 /**
129 * Returns the number of characters per line.
130 *
131 * This value is used to call pango_text::set_characters_per_line
132 * (indirectly).
133 *
134 * @returns The characters per line. This implementation
135 * always returns 0.
136 */
137 virtual unsigned get_characters_per_line() const;
138
139 /**
140 * Returns whether the label should be link_aware, in
141 * in rendering and in searching for links with get_link.
142 *
143 * This value is used to call pango_text::set_link_aware
144 * (indirectly).
145 *
146 * @returns The link aware status. This impl always
147 * always returns false.
148 */
149 virtual bool get_link_aware() const;
150
151 /**
152 * Returns the color string to be used with links.
153 *
154 * This value is used to call pango_text::set_link_color
155 * (indirectly).
156 *
157 * @returns The link color string. This impl returns "#ffff00".
158 *
159 */
160 virtual color_t get_link_color() const;
161
162 /**
163 * See @ref widget::layout_initialize.
164 *
165 * @todo Also handle the tooltip state.
166 * Handle if shrunken_ && use_tooltip_on_label_overflow_.
167 */
168 virtual void layout_initialize(const bool full_initialization) override;
169
170 /** See @ref widget::request_reduce_width. */
171 virtual void request_reduce_width(const unsigned maximum_width) override;
172
173 /** See @ref widget::request_reduce_height. */
174 virtual void request_reduce_height(const unsigned maximum_height) override;
175
176protected:
177 /** See @ref widget::calculate_best_size. */
178 virtual point calculate_best_size() const override;
179
180public:
181 /** See @ref widget::place. */
182 virtual void place(const point& origin, const point& size) override;
183
184 /***** ***** ***** ***** Inherited ***** ***** ***** *****/
185
186 /** See @ref widget::find_at. */
187 virtual widget* find_at(const point& coordinate,
188 const bool must_be_active) override;
189
190 /** See @ref widget::find_at. */
191 virtual const widget* find_at(const point& coordinate,
192 const bool must_be_active) const override;
193
194 /** See @ref widget::find. */
195 widget* find(const std::string_view id, const bool must_be_active) override;
196
197 /** See @ref widget::find. */
198 const widget* find(const std::string_view id, const bool must_be_active) const override;
199
200 /***** ***** ***** setters / getters for members ***** ****** *****/
205
206 void set_use_tooltip_on_label_overflow(const bool use_tooltip = true)
207 {
208 use_tooltip_on_label_overflow_ = use_tooltip;
209 }
210
211 const t_string& get_label() const
212 {
213 return label_;
214 }
215
216 virtual void set_label(const t_string& text);
217
218 virtual void set_use_markup(bool use_markup);
219
220 bool get_use_markup() const
221 {
222 return use_markup_;
223 }
224
225 const t_string& tooltip() const
226 {
227 return tooltip_;
228 }
229
230 // Note setting the tooltip_ doesn't dirty an object.
236
237 const t_string& help_message() const
238 {
239 return help_message_;
240 }
241
242 // Note setting the help_message_ doesn't dirty an object.
247
248 // const versions will be added when needed
249 std::vector<canvas>& get_canvases()
250 {
251 return canvases_;
252 }
253
254 canvas& get_canvas(const unsigned index)
255 {
256 assert(index < canvases_.size());
257 return canvases_[index];
258 }
259
260 virtual void set_text_alignment(const PangoAlignment text_alignment);
261
262 PangoAlignment get_text_alignment() const
263 {
264 return text_alignment_;
265 }
266
267 void set_text_ellipse_mode(const PangoEllipsizeMode ellipse_mode);
268
269 /**
270 * Get the text's ellipsize mode.
271 *
272 * Note that if can_wrap is true, it override the manual setting.
273 */
274 PangoEllipsizeMode get_text_ellipse_mode() const
275 {
276 return can_wrap() ? PANGO_ELLIPSIZE_NONE : text_ellipse_mode_;
277 }
278
279protected:
284
286 {
287 return config_;
288 }
289
290 /**
291 * Casts the current resolution definition config to the respective type of a
292 * derived widget.
293 *
294 * @tparam T The definition type to cast to. Should have a `resolution`
295 * subclass or struct derived from resolution_definition.
296 *
297 * @returns A shared_ptr with the newly cast config.
298 */
299 template<typename T>
300 std::shared_ptr<const typename T::resolution> cast_config_to() const
301 {
302 static_assert(std::is_base_of_v<resolution_definition, typename T::resolution>,
303 "Given type's resolution object does not derive from resolution_definition."
304 );
305
306 return std::static_pointer_cast<const typename T::resolution>(get_config());
307 }
308
309 /***** ***** ***** ***** miscellaneous ***** ***** ***** *****/
310
311 /**
312 * Updates the canvas(ses).
313 *
314 * This function should be called if either the size of the widget changes
315 * or the text on the widget changes.
316 */
317 virtual void update_canvas();
318
319 /**
320 * Resolves and returns the text_font_size
321 *
322 * To allow the text_font_size in the widget definition to be a formula,
323 * call this function which will evaluate the formula (caching the result)
324 * and return the value.
325 */
326 unsigned int get_text_font_size() const;
327
328 /**
329 * Returns the maximum width available for the text.
330 *
331 * This value makes sense after the widget has been given a size, since the
332 * maximum width is based on the width of the widget.
333 */
334 int get_text_maximum_width() const;
335
336 /**
337 * Returns the maximum height available for the text.
338 *
339 * This value makes sense after the widget has been given a size, since the
340 * maximum height is based on the height of the widget.
341 */
342 int get_text_maximum_height() const;
343
344private:
345 /**
346 * The definition is the id of that widget class.
347 *
348 * Eg for a button it [button_definition]id. A button can have multiple
349 * definitions which all look different but for the engine still is a
350 * button.
351 */
352 std::string definition_;
353
354 /** Contain the non-editable text associated with styled_widget. */
356
357 /** Use markup for the label? */
359
360 /**
361 * If the text doesn't fit on the label should the text be used as tooltip?
362 *
363 * This only happens if the tooltip is empty.
364 */
366
367 /**
368 * Tooltip text.
369 *
370 * The hovering event can cause a small tooltip to be shown, this is the
371 * text to be shown. At the moment the tooltip is a single line of text.
372 */
374
375 /**
376 * Tooltip text.
377 *
378 * The help event can cause a tooltip to be shown, this is the text to be
379 * shown. At the moment the tooltip is a single line of text.
380 */
382
383 /**
384 * Contains the pointer to the configuration.
385 *
386 * Every styled_widget has a definition of how it should look, this contains a
387 * pointer to the definition. The definition is resolution dependent, where
388 * the resolution is the size of the Wesnoth application window. Depending
389 * on the resolution widgets can look different, use different fonts.
390 * Windows can use extra scrollbars use abbreviations as text etc.
391 */
393
394 /**
395 * Contains the evaluated text_font_size from the configuration.
396 *
397 * We want to allow formulas in the value of text_font_size, since the desired
398 * font size can depend on parameters of the screen and window. But we don't
399 * want to have to recompute the value of the formula all the time. This member
400 * variable is the cache for the evaluated font size.
401 */
402 mutable unsigned int cached_text_font_size_ = 0;
403
404 /**
405 * Holds all canvas objects for a styled_widget.
406 *
407 * A styled_widget can have multiple states, which are defined in the classes
408 * inheriting from us. For every state there is a separate canvas, which is
409 * stored here. When drawing the state is determined and that canvas is
410 * drawn.
411 */
412 std::vector<canvas> canvases_;
413
414public:
415 /**
416 * Returns the type of this styled_widget.
417 *
418 * This is used as the control_type parameter for @ref get_control.
419 *
420 * Do note that each widget also must have a public static type() function;
421 * it's use to implement this function. The reason for this system is twofold:
422 *
423 * 1) Due to an oddity in C++, one technically may not call a virtual function
424 * in a derived class's *initializer list*, which we do liberally. Calling
425 * it in the constructor *body* is fine, but doing so in the initializer list
426 * is technically undefined behavior and will give "invalid vptr" errors
427 * under UBSanitizer.
428 *
429 * 2) Having a static type getter allows the type string to be fetched without
430 * constructing an instance of the widget. A good example of this usecase is
431 * in build_single_widget_instance.
432 */
433 virtual const std::string& get_control_type() const = 0;
434
435protected:
436 /** See @ref widget::impl_draw_background. */
437 virtual bool impl_draw_background() override;
438
439 /** See @ref widget::impl_draw_foreground. */
440 virtual bool impl_draw_foreground() override;
441
442 /** Exposes font::pango_text::get_token, for the text label of this styled_widget */
443 std::string get_label_token(const point & position, std::string_view delimiters = " \n\r\t") const;
444
445 std::string get_label_link(const point & position) const;
446
447private:
448 /**
449 * Gets the best size for a text.
450 *
451 * @param minimum_size The minimum size of the text.
452 * @param maximum_size The wanted maximum size of the text, if not
453 * possible it's ignored. A value of 0 means
454 * that it's ignored as well.
455 *
456 * @returns The best size.
457 */
458 point get_best_text_size(point minimum_size,
459 point maximum_size = {0, 0}) const;
460
461 /**
462 * Gets whether a widget can shrink past its optimal size even if it's text-based (such as labels);
463 */
464 virtual bool text_can_shrink()
465 {
466 return false;
467 }
468
469 /**
470 * Text renderer object used for size calculations.
471 *
472 * Note this is *not* used to actually render any text, only to get the dimensions of the text for
473 * layout purposes. The actual text rendering happens in the canvas. This is kept as a class member
474 * since creating a pango_text object is quite expensive.
475 *
476 * @todo Maybe if still too slow we might also copy this cache to the
477 * canvas so it can reuse our results, but for now it seems fast enough.
478 * Unfortunately that would make the dependency between the classes bigger
479 * as wanted.
480 */
482
483 /** The alignment of the text in a styled_widget. */
484 PangoAlignment text_alignment_;
485
486 /** The ellipsize mode of the text in a styled_widget. */
487 PangoEllipsizeMode text_ellipse_mode_;
488
489 /** Is the widget smaller as it's best size? */
491
492 /***** ***** ***** signal handlers ***** ****** *****/
493
495 bool& handled,
496 const point& location);
497
499 bool& handled,
500 const point& location);
501
503 bool& handled);
504};
505
506// }---------- BUILDER -----------{
507
508class styled_widget;
509
510namespace implementation
511{
512
514{
515public:
517
519
520 virtual std::unique_ptr<widget> build(const replacements_map& replacements) const override;
521
522 /** Parameters for the styled_widget. */
523 std::string definition;
529};
530
531} // namespace implementation
532
533// }------------ END --------------
534
535} // namespace gui2
This file contains the canvas object which is the part where the widgets draw (temporally) images on.
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
Text class.
Definition text.hpp:78
A simple canvas which can be drawn upon.
Definition canvas.hpp:45
At the moment two kinds of tips are known:
Definition tooltip.cpp:41
void set_wants_mouse_hover(const bool hover=true)
void set_use_tooltip_on_label_overflow(const bool use_tooltip=true)
virtual void set_active(const bool active)=0
Sets the styled_widget's state.
t_string help_message_
Tooltip text.
virtual widget * find_at(const point &coordinate, const bool must_be_active) override
See widget::find_at.
void set_tooltip(const t_string &tooltip)
const t_string & help_message() const
bool use_markup_
Use markup for the label?
PangoAlignment get_text_alignment() const
PangoEllipsizeMode text_ellipse_mode_
The ellipsize mode of the text in a styled_widget.
font::pango_text renderer_
Text renderer object used for size calculations.
virtual unsigned get_state() const =0
Returns the id of the state.
point get_config_maximum_size() const
Gets the best size as defined in the config.
t_string tooltip_
Tooltip text.
std::string definition_
The definition is the id of that widget class.
bool use_tooltip_on_label_overflow_
If the text doesn't fit on the label should the text be used as tooltip?
widget * find(const std::string_view id, const bool must_be_active) override
See widget::find.
bool get_use_tooltip_on_label_overflow() const
const t_string & tooltip() const
int get_text_maximum_width() const
Returns the maximum width available for the text.
virtual unsigned get_characters_per_line() const
Returns the number of characters per line.
canvas & get_canvas(const unsigned index)
point get_config_minimum_size() const
Gets the minimum size as defined in the config.
std::string get_label_link(const point &position) const
int get_text_maximum_height() const
Returns the maximum height available for the text.
void signal_handler_show_helptip(const event::ui_event event, bool &handled, const point &location)
virtual void request_reduce_width(const unsigned maximum_width) override
See widget::request_reduce_width.
virtual void request_reduce_height(const unsigned maximum_height) override
See widget::request_reduce_height.
virtual void layout_initialize(const bool full_initialization) override
See widget::layout_initialize.
virtual void update_canvas()
Updates the canvas(ses).
virtual bool get_link_aware() const
Returns whether the label should be link_aware, in in rendering and in searching for links with get_l...
void set_help_message(const t_string &help_message)
point get_config_default_size() const
Gets the default size as defined in the config.
std::vector< canvas > canvases_
Holds all canvas objects for a styled_widget.
PangoEllipsizeMode get_text_ellipse_mode() const
Get the text's ellipsize mode.
virtual color_t get_link_color() const
Returns the color string to be used with links.
void signal_handler_notify_remove_tooltip(const event::ui_event event, bool &handled)
bool shrunken_
Is the widget smaller as it's best size?
friend class debug_layout_graph
PangoAlignment text_alignment_
The alignment of the text in a styled_widget.
virtual void set_members(const widget_item &data)
Sets the members of the styled_widget.
virtual bool impl_draw_background() override
See widget::impl_draw_background.
point get_best_text_size(point minimum_size, point maximum_size={0, 0}) const
Gets the best size for a text.
std::vector< canvas > & get_canvases()
virtual void place(const point &origin, const point &size) override
See widget::place.
virtual void set_text_alignment(const PangoAlignment text_alignment)
virtual bool get_active() const =0
Gets the active state of the styled_widget.
std::shared_ptr< const typename T::resolution > cast_config_to() const
Casts the current resolution definition config to the respective type of a derived widget.
resolution_definition_ptr config_
Contains the pointer to the configuration.
virtual iteration::walker_ptr create_walker() override
See widget::create_walker.
std::string get_label_token(const point &position, std::string_view delimiters=" \n\r\t") const
Exposes font::pango_text::get_token, for the text label of this styled_widget.
virtual bool impl_draw_foreground() override
See widget::impl_draw_foreground.
bool disable_click_dismiss() const override
See widget::disable_click_dismiss.
virtual void set_label(const t_string &text)
virtual bool text_can_shrink()
Gets whether a widget can shrink past its optimal size even if it's text-based (such as labels);.
void set_text_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
void signal_handler_show_tooltip(const event::ui_event event, bool &handled, const point &location)
virtual void set_use_markup(bool use_markup)
t_string label_
Contain the non-editable text associated with styled_widget.
resolution_definition_ptr get_config()
const t_string & get_label() const
virtual const std::string & get_control_type() const =0
Returns the type of this styled_widget.
bool get_use_markup() const
virtual point calculate_best_size() const override
See widget::calculate_best_size.
resolution_definition_const_ptr get_config() const
unsigned int get_text_font_size() const
Resolves and returns the text_font_size.
unsigned int cached_text_font_size_
Contains the evaluated text_font_size from the configuration.
Base class for all widgets.
Definition widget.hpp:55
virtual bool can_wrap() const
Can the widget wrap.
Definition widget.cpp:225
bool empty() const
Definition tstring.hpp:200
const config * cfg
ui_event
The event sent to the dispatcher.
Definition handler.hpp:115
std::unique_ptr< class walker_base > walker_ptr
Definition widget.hpp:44
Generic file dialog.
std::shared_ptr< resolution_definition > resolution_definition_ptr
std::map< std::string, t_string > widget_item
Definition widget.hpp:33
std::shared_ptr< const resolution_definition > resolution_definition_const_ptr
Contains the implementation details for lexical_cast and shouldn't be used directly.
std::string_view data
Definition picture.cpp:188
The basic class for representing 8-bit RGB or RGBA colour values.
Definition color.hpp:51
Contains the info needed to instantiate a widget.
virtual std::unique_ptr< widget > build() const =0
std::map< std::string, std::shared_ptr< builder_widget > > replacements_map
The replacements type is used to define replacement types.
virtual std::unique_ptr< widget > build() const=0
std::string definition
Parameters for the styled_widget.
Holds a 2D point.
Definition point.hpp:25