The Battle for Wesnoth  1.19.20+dev
rich_label.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2024 - 2025
3  by Subhraman Sarkar (babaissarkar) <sbmskmm@protonmail.com>
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 "color.hpp"
20 
23 
24 namespace gui2
25 {
26 namespace implementation
27 {
28  struct builder_rich_label;
29 }
30 
31 // ------------ WIDGET -----------{
32 
33 /**
34  *
35  * A rich_label takes marked up text and shows it correctly formatted and wrapped but no scrollbars are provided.
36  */
37 class rich_label : public styled_widget
38 {
40 
41 public:
42  explicit rich_label(const implementation::builder_rich_label& builder);
43 
44  virtual bool can_wrap() const override
45  {
46  return can_wrap_ || characters_per_line_ != 0;
47  }
48 
49  virtual unsigned get_characters_per_line() const override
50  {
51  return characters_per_line_;
52  }
53 
54  virtual bool get_link_aware() const override
55  {
56  return link_aware_;
57  }
58 
59  virtual color_t get_link_color() const override
60  {
61  return link_color_;
62  }
63 
64  virtual void set_active(const bool active) override;
65 
66  virtual bool get_active() const override
67  {
68  return state_ != DISABLED;
69  }
70 
71  virtual unsigned get_state() const override
72  {
73  return state_;
74  }
75 
76  bool disable_click_dismiss() const override
77  {
78  return false;
79  }
80 
81  virtual bool can_mouse_focus() const override
82  {
83  return !tooltip().empty() || get_link_aware();
84  }
85 
86  virtual void request_reduce_height(const unsigned /*maximum_height*/) override {};
87 
88  virtual void update_canvas() override;
89 
90  /* **** ***** ***** setters / getters for members ***** ****** **** */
91 
92  void set_can_wrap(const bool wrap)
93  {
94  can_wrap_ = wrap;
95  }
96 
97  void set_link_aware(bool l);
98 
99  void set_link_color(const color_t& color);
100 
101  void set_can_shrink(bool can_shrink)
102  {
103  can_shrink_ = can_shrink;
104  }
105 
106  void set_font_family(const std::string& font_family)
107  {
108  font_family_ = font_family;
109  }
110 
111  void set_font_size(int font_size)
112  {
113  font_size_ = font_size;
114  }
115 
116  void set_font_style(const std::string& font_style)
117  {
118  font_style_ = font_style;
119  }
120 
121  void set_text_alpha(unsigned short alpha);
122 
123  // Show text marked up with help markup
124  void set_label(const t_string& text) override;
125 
126  // Show a given DOM (given as a config)
127  void set_dom(const config& dom);
128 
129  int get_width()
130  {
131  return init_w_;
132  }
133 
134  // NOTE: set_label() must be done after this so the text can be
135  // laid out with the new width.
136  void set_width(const int width)
137  {
138  init_w_ = width;
139  }
140 
141  // Given a parsed config from help markup,
142  // layout it into a config that can be understood by canvas
143  std::pair<config, point> get_parsed_text(
144  const config& parsed_text,
145  const point& origin,
146  const unsigned init_width,
147  const bool finalize = false);
148 
149  // Attaches a callback function that will be called when a link is clicked
150  void register_link_callback(std::function<void(std::string)> link_handler);
151 
152 private:
153  /**
154  * Possible states of the widget.
155  *
156  * Note the order of the states must be the same as defined in settings.hpp.
157  */
158  enum state_t {
161  };
162 
163  void set_state(const state_t state);
164 
165  /**
166  * Current state of the widget.
167  *
168  * The state of the widget determines what to render and how the widget
169  * reacts to certain 'events'.
170  */
172 
173  /** Holds the rich_label can wrap or not. */
174  bool can_wrap_;
175 
176  /**
177  * The maximum number of characters per line.
178  *
179  * The maximum is not an exact maximum, it uses the average character width.
180  */
182 
183  /**
184  * Whether the rich_label is link aware, rendering links with special formatting
185  * and handling click events.
186  */
188 
189  /**
190  * Base text color, enabled state
191  */
193 
194  /**
195  * Base text color, disabled state
196  */
198 
199  /**
200  * What color links will be rendered in.
201  */
203 
204  /**
205  * Color variables that can be used in place of colors strings, like `<row bgcolor=color1>`
206  */
207  std::map<std::string, color_t> predef_colors_;
208 
209  /**
210  * Base font family
211  */
212  std::string font_family_;
213 
214  /**
215  * Base font size
216  */
218 
219  /**
220  * Base font style
221  */
222  std::string font_style_;
223 
225 
226  unsigned short text_alpha_;
227 
228  /** Inherited from styled_widget. */
229  virtual bool text_can_shrink() override
230  {
231  return can_shrink_;
232  }
233 
234  /** Final list of shapes to be drawn on the canvas. */
236 
237  /** Width and height of the canvas */
238  unsigned init_w_;
240 
242 
243  /** Padding */
244  int padding_;
245 
246  /** If color is a predefined color set in resolution, return it, otherwise decode using `font::string_to_color`. */
247  color_t get_color(const std::string& color);
248 
249  /** Create template for text config that can be shown in canvas */
250  void default_text_config(config* txt_ptr, const point& pos, const int max_width, const t_string& text = "");
251 
252  std::pair<std::size_t, std::size_t> add_text(config& curr_item, const std::string& text);
253  void add_attribute(config& curr_item, const std::string& attr_name, const std::string& extra_data = "", std::size_t start = 0, std::size_t end = 0);
254  std::pair<std::size_t, std::size_t> add_text_with_attribute(config& curr_item, const std::string& text, const std::string& attr_name = "", const std::string& extra_data = "");
255 
256  void add_link(config& curr_item, const std::string& name, const std::string& dest, const point& origin, int img_width);
257 
258  /** size calculation functions */
259  point get_text_size(config& text_cfg, unsigned width = 0) const;
260  point get_image_size(config& img_cfg) const;
261 
262  wfl::map_formula_callable setup_text_renderer(config text_cfg, unsigned width = 0) const;
263 
264  std::size_t get_split_location(std::string_view text, const point& pos);
265 
266  /** link variables and functions */
267  std::vector<std::pair<rect, std::string>> links_;
268 
269  std::function<void(std::string)> link_handler_;
270 
271  int get_offset_from_xy(const point& position) const
272  {
273  return std::get<0>(font::get_text_renderer().xy_to_index(position));
274  }
275 
276  point get_xy_from_offset(const unsigned offset) const
277  {
279  }
280 
281  point calculate_best_size() const override;
282 
283  void request_reduce_width(const unsigned maximum_width) override;
284 
285  void place(const point& origin, const point& size) override;
286 
287 public:
288  /** Static type getter that does not rely on the widget being constructed. */
289  static const std::string& type();
290 
291 private:
292  /** Inherited from styled_widget, implemented by REGISTER_WIDGET. */
293  virtual const std::string& get_control_type() const override;
294 
295  /* **** ***** ***** signal handlers ***** ****** **** */
296 
297  /**
298  * Left click signal handler: checks if we clicked on a hyperlink
299  */
300  void signal_handler_left_button_click(bool& handled);
301 
302  /**
303  * Mouse motion signal handler: checks if the cursor is on a hyperlink
304  */
305  void signal_handler_mouse_motion(bool& handled, const point& coordinate);
306 
307  /**
308  * Mouse leave signal handler: checks if the cursor left a hyperlink
309  */
310  void signal_handler_mouse_leave(bool& handled);
311 
312  /**
313  * Implementation detail for (re)setting the hyperlink cursor.
314  */
315  void update_mouse_cursor(bool enable);
316 };
317 
318 // }---------- DEFINITION ---------{
319 
321 {
322 
323  explicit rich_label_definition(const config& cfg);
324 
326  {
327  explicit resolution(const config& cfg);
328 
331  std::string font_family;
333  std::string font_style;
334  std::map<std::string, color_t> colors;
335  };
336 };
337 
338 // }---------- BUILDER -----------{
339 
340 namespace implementation
341 {
342 
344 {
345  builder_rich_label(const config& cfg);
346 
348 
349  virtual std::unique_ptr<widget> build() const override;
350 
351  PangoAlignment text_alignment;
353  unsigned padding;
354 };
355 
356 } // namespace implementation
357 
358 // }------------ END --------------
359 
360 } // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:157
point get_cursor_position(const unsigned offset, const unsigned line=0) const
Gets the location for the cursor, in drawing coordinates.
Definition: text.cpp:225
A rich_label takes marked up text and shows it correctly formatted and wrapped but no scrollbars are ...
Definition: rich_label.hpp:38
point calculate_best_size() const override
See widget::calculate_best_size.
Definition: rich_label.cpp:272
unsigned characters_per_line_
The maximum number of characters per line.
Definition: rich_label.hpp:181
bool disable_click_dismiss() const override
Does the widget disable easy close?
Definition: rich_label.hpp:76
void add_link(config &curr_item, const std::string &name, const std::string &dest, const point &origin, int img_width)
Definition: rich_label.cpp:177
void signal_handler_mouse_motion(bool &handled, const point &coordinate)
Mouse motion signal handler: checks if the cursor is on a hyperlink.
Definition: rich_label.cpp:918
void set_can_wrap(const bool wrap)
Definition: rich_label.hpp:92
state_t state_
Current state of the widget.
Definition: rich_label.hpp:171
void set_state(const state_t state)
Definition: rich_label.cpp:858
color_t text_color_enabled_
Base text color, enabled state.
Definition: rich_label.hpp:192
virtual bool get_active() const override
Gets the active state of the styled_widget.
Definition: rich_label.hpp:66
point get_text_size(config &text_cfg, unsigned width=0) const
size calculation functions
Definition: rich_label.cpp:111
bool can_wrap_
Holds the rich_label can wrap or not.
Definition: rich_label.hpp:174
virtual color_t get_link_color() const override
Returns the color string to be used with links.
Definition: rich_label.hpp:59
std::function< void(std::string)> link_handler_
Definition: rich_label.hpp:269
virtual unsigned get_state() const override
Returns the id of the state.
Definition: rich_label.hpp:71
virtual void update_canvas() override
Updates the canvas(ses).
Definition: rich_label.cpp:812
int padding_
Padding.
Definition: rich_label.hpp:244
void signal_handler_mouse_leave(bool &handled)
Mouse leave signal handler: checks if the cursor left a hyperlink.
Definition: rich_label.cpp:939
std::vector< std::pair< rect, std::string > > links_
link variables and functions
Definition: rich_label.hpp:267
void add_attribute(config &curr_item, const std::string &attr_name, const std::string &extra_data="", std::size_t start=0, std::size_t end=0)
Definition: rich_label.cpp:141
void place(const point &origin, const point &size) override
See widget::place.
Definition: rich_label.cpp:277
int font_size_
Base font size.
Definition: rich_label.hpp:217
point get_image_size(config &img_cfg) const
Definition: rich_label.cpp:120
config shapes_
Final list of shapes to be drawn on the canvas.
Definition: rich_label.hpp:235
virtual bool can_mouse_focus() const override
Whether the mouse move/click event go 'through' this widget.
Definition: rich_label.hpp:81
void set_width(const int width)
Definition: rich_label.hpp:136
unsigned short text_alpha_
Definition: rich_label.hpp:226
std::string font_family_
Base font family.
Definition: rich_label.hpp:212
unsigned init_w_
Width and height of the canvas.
Definition: rich_label.hpp:238
void set_font_style(const std::string &font_style)
Definition: rich_label.hpp:116
virtual const std::string & get_control_type() const override
Inherited from styled_widget, implemented by REGISTER_WIDGET.
void set_dom(const config &dom)
Definition: rich_label.cpp:250
void set_can_shrink(bool can_shrink)
Definition: rich_label.hpp:101
point get_xy_from_offset(const unsigned offset) const
Definition: rich_label.hpp:276
color_t get_color(const std::string &color)
If color is a predefined color set in resolution, return it, otherwise decode using font::string_to_c...
Definition: rich_label.cpp:92
std::pair< config, point > get_parsed_text(const config &parsed_text, const point &origin, const unsigned init_width, const bool finalize=false)
Definition: rich_label.cpp:286
void request_reduce_width(const unsigned maximum_width) override
See widget::request_reduce_width.
Definition: rich_label.cpp:263
virtual void set_active(const bool active) override
Sets the styled_widget's state.
Definition: rich_label.cpp:833
std::string font_style_
Base font style.
Definition: rich_label.hpp:222
state_t
Possible states of the widget.
Definition: rich_label.hpp:158
void register_link_callback(std::function< void(std::string)> link_handler)
Definition: rich_label.cpp:866
virtual void request_reduce_height(const unsigned) override
See widget::request_reduce_height.
Definition: rich_label.hpp:86
void signal_handler_left_button_click(bool &handled)
Left click signal handler: checks if we clicked on a hyperlink.
Definition: rich_label.cpp:882
void set_font_size(int font_size)
Definition: rich_label.hpp:111
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
int get_offset_from_xy(const point &position) const
Definition: rich_label.hpp:271
bool link_aware_
Whether the rich_label is link aware, rendering links with special formatting and handling click even...
Definition: rich_label.hpp:187
std::pair< std::size_t, std::size_t > add_text(config &curr_item, const std::string &text)
Definition: rich_label.cpp:132
virtual unsigned get_characters_per_line() const override
Returns the number of characters per line.
Definition: rich_label.hpp:49
wfl::map_formula_callable setup_text_renderer(config text_cfg, unsigned width=0) const
Definition: rich_label.cpp:98
virtual bool can_wrap() const override
Can the widget wrap.
Definition: rich_label.hpp:44
void set_link_color(const color_t &color)
Definition: rich_label.cpp:849
std::map< std::string, color_t > predef_colors_
Color variables that can be used in place of colors strings, like <row bgcolor=color1>
Definition: rich_label.hpp:207
void set_link_aware(bool l)
Definition: rich_label.cpp:840
virtual bool get_link_aware() const override
Returns whether the label should be link_aware, in in rendering and in searching for links with get_l...
Definition: rich_label.hpp:54
rich_label(const implementation::builder_rich_label &builder)
Definition: rich_label.cpp:65
void default_text_config(config *txt_ptr, const point &pos, const int max_width, const t_string &text="")
Create template for text config that can be shown in canvas.
Definition: rich_label.cpp:786
void set_font_family(const std::string &font_family)
Definition: rich_label.hpp:106
virtual bool text_can_shrink() override
Inherited from styled_widget.
Definition: rich_label.hpp:229
void set_text_alpha(unsigned short alpha)
Definition: rich_label.cpp:824
color_t link_color_
What color links will be rendered in.
Definition: rich_label.hpp:202
void set_label(const t_string &text) override
Definition: rich_label.cpp:258
void update_mouse_cursor(bool enable)
Implementation detail for (re)setting the hyperlink cursor.
Definition: rich_label.cpp:953
color_t text_color_disabled_
Base text color, disabled state.
Definition: rich_label.hpp:197
std::size_t get_split_location(std::string_view text, const point &pos)
Definition: rich_label.cpp:231
std::pair< std::size_t, std::size_t > add_text_with_attribute(config &curr_item, const std::string &text, const std::string &attr_name="", const std::string &extra_data="")
Definition: rich_label.cpp:166
const t_string & tooltip() const
bool empty() const
Definition: tstring.hpp:200
const config * cfg
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
pango_text & get_text_renderer()
Returns a reference to a static pango_text object.
Definition: text.cpp:960
Generic file dialog.
Contains the implementation details for lexical_cast and shouldn't be used directly.
static log_domain dom("general")
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:81
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:51
virtual std::unique_ptr< widget > build() const override
virtual std::unique_ptr< widget > build() const=0
std::map< std::string, color_t > colors
Definition: rich_label.hpp:334
rich_label_definition(const config &cfg)
Definition: rich_label.cpp:968
Holds a 2D point.
Definition: point.hpp:25