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