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