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 
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 
241  /** Padding */
242  int padding_;
243 
244  /** If color is a predefined color set in resolution, return it, otherwise decode using `font::string_to_color`. */
245  color_t get_color(const std::string& color);
246 
247  /** Create template for text config that can be shown in canvas */
248  void default_text_config(config* txt_ptr, const point& pos, const int max_width, const t_string& text = "");
249 
250  std::pair<size_t, size_t> add_text(config& curr_item, const std::string& text);
251  void add_attribute(config& curr_item, const std::string& attr_name, const std::string& extra_data = "", size_t start = 0, size_t end = 0);
252  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 = "");
253 
254  void add_link(config& curr_item, const std::string& name, const std::string& dest, const point& origin, int img_width);
255 
256  /** size calculation functions */
257  point get_text_size(config& text_cfg, unsigned width = 0) const;
258  point get_image_size(config& img_cfg) const;
259 
260  wfl::map_formula_callable setup_text_renderer(config text_cfg, unsigned width = 0) const;
261 
262  size_t get_split_location(std::string_view text, const point& pos);
263 
264  /** link variables and functions */
265  std::vector<std::pair<rect, std::string>> links_;
266 
267  std::function<void(std::string)> link_handler_;
268 
269  int get_offset_from_xy(const point& position) const
270  {
271  return font::get_text_renderer().xy_to_index(position).first;
272  }
273 
274  point get_xy_from_offset(const unsigned offset) const
275  {
277  }
278 
279  point calculate_best_size() const override { return size_; };
280 
281 public:
282  /** Static type getter that does not rely on the widget being constructed. */
283  static const std::string& type();
284 
285 private:
286  /** Inherited from styled_widget, implemented by REGISTER_WIDGET. */
287  virtual const std::string& get_control_type() const override;
288 
289  /* **** ***** ***** signal handlers ***** ****** **** */
290 
291  /**
292  * Left click signal handler: checks if we clicked on a hyperlink
293  */
294  void signal_handler_left_button_click(bool& handled);
295 
296  /**
297  * Mouse motion signal handler: checks if the cursor is on a hyperlink
298  */
299  void signal_handler_mouse_motion(bool& handled, const point& coordinate);
300 
301  /**
302  * Mouse leave signal handler: checks if the cursor left a hyperlink
303  */
304  void signal_handler_mouse_leave(bool& handled);
305 
306  /**
307  * Implementation detail for (re)setting the hyperlink cursor.
308  */
309  void update_mouse_cursor(bool enable);
310 };
311 
312 // }---------- DEFINITION ---------{
313 
315 {
316 
317  explicit rich_label_definition(const config& cfg);
318 
320  {
321  explicit resolution(const config& cfg);
322 
325  std::string font_family;
327  std::string font_style;
328  std::map<std::string, color_t> colors;
329  };
330 };
331 
332 // }---------- BUILDER -----------{
333 
334 namespace implementation
335 {
336 
338 {
339  builder_rich_label(const config& cfg);
340 
342 
343  virtual std::unique_ptr<widget> build() const override;
344 
345  PangoAlignment text_alignment;
348  unsigned padding;
349 };
350 
351 } // namespace implementation
352 
353 // }------------ END --------------
354 
355 } // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
std::pair< int, int > xy_to_index(const point &position) const
Definition: text.cpp:308
point get_cursor_position(const unsigned offset, const unsigned line=0) const
Gets the location for the cursor, in drawing coordinates.
Definition: text.cpp:224
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.hpp:279
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:882
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:827
size_t get_split_location(std::string_view text, const point &pos)
Definition: rich_label.cpp:231
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:267
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:166
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:781
int padding_
Padding.
Definition: rich_label.hpp:242
std::pair< size_t, size_t > add_text(config &curr_item, const std::string &text)
Definition: rich_label.cpp:132
void signal_handler_mouse_leave(bool &handled)
Mouse leave signal handler: checks if the cursor left a hyperlink.
Definition: rich_label.cpp:903
std::vector< std::pair< rect, std::string > > links_
link variables and functions
Definition: rich_label.hpp:265
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
void add_attribute(config &curr_item, const std::string &attr_name, const std::string &extra_data="", size_t start=0, size_t end=0)
Definition: rich_label.cpp:141
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:274
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:260
virtual void set_active(const bool active) override
Sets the styled_widget's state.
Definition: rich_label.cpp:802
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:835
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:851
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:269
bool link_aware_
Whether the rich_label is link aware, rendering links with special formatting and handling click even...
Definition: rich_label.hpp:187
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:818
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:809
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:755
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:793
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:256
void update_mouse_cursor(bool enable)
Implementation detail for (re)setting the hyperlink cursor.
Definition: rich_label.cpp:917
color_t text_color_disabled_
Base text color, disabled state.
Definition: rich_label.hpp:197
const t_string & tooltip() const
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:964
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.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:61
virtual std::unique_ptr< widget > build() const override
Definition: rich_label.cpp:975
virtual std::unique_ptr< widget > build() const=0
std::map< std::string, color_t > colors
Definition: rich_label.hpp:328
rich_label_definition(const config &cfg)
Definition: rich_label.cpp:932
Holds a 2D point.
Definition: point.hpp:25