The Battle for Wesnoth  1.19.21+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) override;
65 
66  virtual bool get_active() const override
67  {
68  return true; // Always enabled
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  typedef std::unique_ptr<canvas::shape> shape_ptr;
142 
143  // Given a parsed config from help markup,
144  // layout it into a config that can be understood by canvas
145  std::pair<std::vector<shape_ptr>, point> get_parsed_text(
146  const config& parsed_text,
147  const point& origin,
148  const unsigned init_width,
149  const bool finalize = false);
150 
151  // Attaches a callback function that will be called when a link is clicked
152  void register_link_callback(std::function<void(std::string)> link_handler);
153 
154 private:
155  /**
156  * Possible states of the widget.
157  *
158  * Note the order of the states must be the same as defined in settings.hpp.
159  */
160  enum state_t { ENABLED }; // Always enabled
161 
162  void set_state(const state_t state);
163 
164  /**
165  * Current state of the widget.
166  *
167  * The state of the widget determines what to render and how the widget
168  * reacts to certain 'events'.
169  */
171 
172  /** Holds the rich_label can wrap or not. */
173  bool can_wrap_;
174 
175  /**
176  * The maximum number of characters per line.
177  *
178  * The maximum is not an exact maximum, it uses the average character width.
179  */
181 
182  /**
183  * Whether the rich_label is link aware, rendering links with special formatting
184  * and handling click events.
185  */
187 
188  /**
189  * Base text color, enabled state
190  */
192 
193  /**
194  * Base text color, disabled state
195  */
197 
198  /**
199  * What color links will be rendered in.
200  */
202 
203  /**
204  * Color variables that can be used in place of colors strings, like `<row bgcolor=color1>`
205  */
206  std::map<std::string, color_t> predef_colors_;
207 
208  /**
209  * Base font family
210  */
211  std::string font_family_;
212 
213  /**
214  * Base font size
215  */
217 
218  /**
219  * Base font style
220  */
221  std::string font_style_;
222 
224 
225  unsigned short text_alpha_;
226 
227  /** Inherited from styled_widget. */
228  virtual bool text_can_shrink() override
229  {
230  return can_shrink_;
231  }
232 
233  /** Width and height of the canvas */
234  unsigned init_w_;
236 
238 
239  /** Padding */
240  int padding_;
241 
242  /** If color is a predefined color set in resolution, return it, otherwise decode using `font::string_to_color`. */
243  color_t get_color(const std::string& color);
244 
245  /** Create template for text config that can be shown in canvas */
246  std::unique_ptr<gui2::text_shape> new_text_shape(const point& origin, const int max_width);
247 
248  std::pair<std::size_t, std::size_t> add_text_with_attribute(
249  text_shape& tshape,
250  const t_string& text,
251  const std::string& attr_name = "",
252  const std::string& extra_data = "");
253 
254  void add_link(
255  text_shape& tshape,
256  const std::string& name,
257  const std::string& dest,
258  const point& origin,
259  int img_width);
260 
261  /** size calculation functions */
262  wfl::map_formula_callable setup_text_renderer(text_shape& tshape, unsigned width) const;
263  point get_text_size(text_shape& tshape, unsigned width) const;
264  point get_image_size(const std::string& path) const;
265 
266  std::size_t get_split_location(std::string_view text, const point& pos);
267 
268  /** link variables and functions */
269  std::vector<std::pair<rect, std::string>> links_;
270 
271  std::function<void(std::string)> link_handler_;
272 
273  int get_offset_from_xy(const point& position) const
274  {
275  return std::get<0>(font::get_text_renderer().xy_to_index(position));
276  }
277 
278  point get_xy_from_offset(const unsigned offset) const
279  {
281  }
282 
283  point calculate_best_size() const override;
284 
285  void request_reduce_width(const unsigned maximum_width) override;
286 
287  void place(const point& origin, const point& size) override;
288 
289 public:
290  /** Static type getter that does not rely on the widget being constructed. */
291  static const std::string& type();
292 
293 private:
294  /** Inherited from styled_widget, implemented by REGISTER_WIDGET. */
295  virtual const std::string& get_control_type() const override;
296 
297  /* **** ***** ***** signal handlers ***** ****** **** */
298 
299  /**
300  * Left click signal handler: checks if we clicked on a hyperlink
301  */
302  void signal_handler_left_button_click(bool& handled);
303 
304  /**
305  * Mouse motion signal handler: checks if the cursor is on a hyperlink
306  */
307  void signal_handler_mouse_motion(bool& handled, const point& coordinate);
308 
309  /**
310  * Mouse leave signal handler: checks if the cursor left a hyperlink
311  */
312  void signal_handler_mouse_leave(bool& handled);
313 
314  /**
315  * Implementation detail for (re)setting the hyperlink cursor.
316  */
317  void update_mouse_cursor(bool enable);
318 };
319 
320 // }---------- DEFINITION ---------{
321 
323 {
324 
325  explicit rich_label_definition(const config& cfg);
326 
328  {
329  explicit resolution(const config& cfg);
330 
333  std::string font_family;
335  std::string font_style;
336  std::map<std::string, color_t> colors;
337  };
338 };
339 
340 // }---------- BUILDER -----------{
341 
342 namespace implementation
343 {
344 
346 {
347  builder_rich_label(const config& cfg);
348 
350 
351  virtual std::unique_ptr<widget> build() const override;
352 
353  PangoAlignment text_alignment;
355  unsigned padding;
356 };
357 
358 } // namespace implementation
359 
360 // }------------ END --------------
361 
362 } // 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:241
unsigned characters_per_line_
The maximum number of characters per line.
Definition: rich_label.hpp:180
bool disable_click_dismiss() const override
Does the widget disable easy close?
Definition: rich_label.hpp:76
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:857
void set_can_wrap(const bool wrap)
Definition: rich_label.hpp:92
state_t state_
Current state of the widget.
Definition: rich_label.hpp:170
virtual void set_active(const bool) override
Sets the styled_widget's state.
Definition: rich_label.cpp:774
void set_state(const state_t state)
Definition: rich_label.cpp:797
color_t text_color_enabled_
Base text color, enabled state.
Definition: rich_label.hpp:191
virtual bool get_active() const override
Gets the active state of the styled_widget.
Definition: rich_label.hpp:66
bool can_wrap_
Holds the rich_label can wrap or not.
Definition: rich_label.hpp:173
virtual color_t get_link_color() const override
Returns the color string to be used with links.
Definition: rich_label.hpp:59
std::unique_ptr< canvas::shape > shape_ptr
Definition: rich_label.hpp:141
std::function< void(std::string)> link_handler_
Definition: rich_label.hpp:271
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:754
std::pair< std::vector< shape_ptr >, point > get_parsed_text(const config &parsed_text, const point &origin, const unsigned init_width, const bool finalize=false)
Definition: rich_label.cpp:255
int padding_
Padding.
Definition: rich_label.hpp:240
void signal_handler_mouse_leave(bool &handled)
Mouse leave signal handler: checks if the cursor left a hyperlink.
Definition: rich_label.cpp:878
std::vector< std::pair< rect, std::string > > links_
link variables and functions
Definition: rich_label.hpp:269
void place(const point &origin, const point &size) override
See widget::place.
Definition: rich_label.cpp:246
int font_size_
Base font size.
Definition: rich_label.hpp:216
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:225
std::unique_ptr< gui2::text_shape > new_text_shape(const point &origin, const int max_width)
Create template for text config that can be shown in canvas.
Definition: rich_label.cpp:737
std::string font_family_
Base font family.
Definition: rich_label.hpp:211
unsigned init_w_
Width and height of the canvas.
Definition: rich_label.hpp:234
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:213
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:278
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
wfl::map_formula_callable setup_text_renderer(text_shape &tshape, unsigned width) const
size calculation functions
Definition: rich_label.cpp:98
void request_reduce_width(const unsigned maximum_width) override
See widget::request_reduce_width.
Definition: rich_label.cpp:232
std::string font_style_
Base font style.
Definition: rich_label.hpp:221
state_t
Possible states of the widget.
Definition: rich_label.hpp:160
void register_link_callback(std::function< void(std::string)> link_handler)
Definition: rich_label.cpp:805
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:821
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:273
point get_image_size(const std::string &path) const
Definition: rich_label.cpp:119
bool link_aware_
Whether the rich_label is link aware, rendering links with special formatting and handling click even...
Definition: rich_label.hpp:186
virtual unsigned get_characters_per_line() const override
Returns the number of characters per line.
Definition: rich_label.hpp:49
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:788
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:206
void set_link_aware(bool l)
Definition: rich_label.cpp:779
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 add_link(text_shape &tshape, const std::string &name, const std::string &dest, const point &origin, int img_width)
Definition: rich_label.cpp:135
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:228
void set_text_alpha(unsigned short alpha)
Definition: rich_label.cpp:765
color_t link_color_
What color links will be rendered in.
Definition: rich_label.hpp:201
void set_label(const t_string &text) override
Definition: rich_label.cpp:227
point get_text_size(text_shape &tshape, unsigned width) const
Definition: rich_label.cpp:110
void update_mouse_cursor(bool enable)
Implementation detail for (re)setting the hyperlink cursor.
Definition: rich_label.cpp:892
color_t text_color_disabled_
Base text color, disabled state.
Definition: rich_label.hpp:196
std::pair< std::size_t, std::size_t > add_text_with_attribute(text_shape &tshape, const t_string &text, const std::string &attr_name="", const std::string &extra_data="")
Definition: rich_label.cpp:124
std::size_t get_split_location(std::string_view text, const point &pos)
Definition: rich_label.cpp:189
const t_string & tooltip() const
bool empty() const
Definition: tstring.hpp:200
const config * cfg
pango_text & get_text_renderer()
Returns a reference to a static pango_text object.
Definition: text.cpp:960
std::string path
Definition: filesystem.cpp:106
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
Definition: rich_label.cpp:948
virtual std::unique_ptr< widget > build() const=0
std::map< std::string, color_t > colors
Definition: rich_label.hpp:336
rich_label_definition(const config &cfg)
Definition: rich_label.cpp:907
Holds a 2D point.
Definition: point.hpp:25