The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
label.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 - 2025
3 by Mark de Wever <koraq@xs4all.nl>
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#define GETTEXT_DOMAIN "wesnoth-lib"
17
18#include "gui/widgets/label.hpp"
19
20#include "gui/core/log.hpp"
21
25
26#include "cursor.hpp"
27#include "desktop/clipboard.hpp"
28#include "desktop/open.hpp"
30#include "gettext.hpp"
31#include "wml_exception.hpp"
32
33#include <functional>
34#include <string>
35
36namespace gui2
37{
38
39// ------------ WIDGET -----------{
40
42
43label::label(const implementation::builder_label& builder)
44 : styled_widget(builder, type())
45 , state_(ENABLED)
46 , can_wrap_(builder.wrap)
47 , characters_per_line_(builder.characters_per_line)
48 , link_aware_(builder.link_aware)
49 , link_color_(font::YELLOW_COLOR)
50 , can_shrink_(builder.can_shrink)
51 , text_alpha_(ALPHA_OPAQUE)
52{
53 connect_signal<event::LEFT_BUTTON_CLICK>(
54 std::bind(&label::signal_handler_left_button_click, this, std::placeholders::_3));
55 connect_signal<event::RIGHT_BUTTON_CLICK>(
56 std::bind(&label::signal_handler_right_button_click, this, std::placeholders::_3));
57 connect_signal<event::MOUSE_MOTION>(
58 std::bind(&label::signal_handler_mouse_motion, this, std::placeholders::_3, std::placeholders::_5));
59 connect_signal<event::MOUSE_LEAVE>(
60 std::bind(&label::signal_handler_mouse_leave, this, std::placeholders::_3));
61}
62
64{
65 // Inherit.
67
68 for(auto& tmp : get_canvases()) {
69 tmp.set_variable("text_alpha", wfl::variant(text_alpha_));
70 }
71}
72
73void label::set_text_alpha(unsigned short alpha)
74{
75 if(alpha != text_alpha_) {
76 text_alpha_ = alpha;
79 }
80}
81
82void label::set_active(const bool active)
83{
84 if(get_active() != active) {
85 set_state(active ? ENABLED : DISABLED);
86 }
87}
88
89void label::set_link_aware(bool link_aware)
90{
91 if(link_aware != link_aware_) {
92 link_aware_ = link_aware;
95 }
96}
97
99{
100 if(color != link_color_) {
101 link_color_ = color;
103 queue_redraw();
104 }
105}
106
107void label::set_state(const state_t state)
108{
109 if(state != state_) {
110 state_ = state;
111 queue_redraw();
112 }
113}
114
116{
117 DBG_GUI_E << "label click";
118
119 if(!get_link_aware()) {
120 return; // without marking event as "handled".
121 }
122
124 show_message("", _("Opening links is not supported, contact your packager"), dialogs::message::auto_close);
125 handled = true;
126 return;
127 }
128
129 std::string link = get_label_link(get_mouse_position());
130
131 if(link.empty()) {
132 return; // without marking event as "handled"
133 }
134
135 DBG_GUI_E << "Clicked Link:\"" << link << "\"";
136
137 const int res = show_message(_("Open link?"), link, dialogs::message::yes_no_buttons);
138 if(res == gui2::retval::OK) {
140 }
141
142 handled = true;
143}
144
146{
147 DBG_GUI_E << "label right click";
148
149 if(!get_link_aware()) {
150 return; // without marking event as "handled".
151 }
152
153 std::string link = get_label_link(get_mouse_position());
154 if(link.empty()) {
155 return ; // without marking event as "handled"
156 }
157
158 DBG_GUI_E << "Right Clicked Link:\"" << link << "\"";
159
161
162 show_message("", _("Copied link!"), dialogs::message::auto_close);
163
164 handled = true;
165}
166
167void label::signal_handler_mouse_motion(bool& handled, const point& coordinate)
168{
169 DBG_GUI_E << "label mouse motion";
170
171 if(!get_link_aware()) {
172 return; // without marking event as "handled"
173 }
174
175 update_mouse_cursor(!get_label_link(coordinate).empty());
176
177 handled = true;
178}
179
181{
182 DBG_GUI_E << "label mouse leave";
183
184 if(!get_link_aware()) {
185 return; // without marking event as "handled"
186 }
187
188 // We left the widget, so just unconditionally reset the cursor
189 update_mouse_cursor(false);
190
191 handled = true;
192}
193
195{
196 // Someone else may set the mouse cursor for us to something unusual (e.g.
197 // the WAIT cursor) so we ought to mess with that only if it's set to
198 // NORMAL or HYPERLINK.
199
200 if(enable && cursor::get() == cursor::NORMAL) {
202 } else if(!enable && cursor::get() == cursor::HYPERLINK) {
204 }
205}
206
207// }---------- DEFINITION ---------{
208
211{
212 DBG_GUI_P << "Parsing label " << id;
213
214 load_resolutions<resolution>(cfg);
215}
216
219 , link_color(cfg["link_color"].empty() ? font::YELLOW_COLOR : color_t::from_rgba_string(cfg["link_color"].str()))
220{
221 // Note the order should be the same as the enum state_t is label.hpp.
222 state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_enabled", missing_mandatory_wml_tag("label_definition][resolution", "state_enabled")));
223 state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_disabled", missing_mandatory_wml_tag("label_definition][resolution", "state_disabled")));
224}
225
226// }---------- BUILDER -----------{
227
228namespace implementation
229{
230
231builder_label::builder_label(const config& cfg)
233 , wrap(cfg["wrap"].to_bool())
234 , characters_per_line(cfg["characters_per_line"].to_unsigned())
235 , text_alignment(decode_text_alignment(cfg["text_alignment"]))
236 , can_shrink(cfg["can_shrink"].to_bool(false))
237 , link_aware(cfg["link_aware"].to_bool(false))
238{
239}
240
241std::unique_ptr<widget> builder_label::build() const
242{
243 auto lbl = std::make_unique<label>(*this);
244
245 const auto conf = lbl->cast_config_to<label_definition>();
246 assert(conf);
247
248 lbl->set_text_alignment(text_alignment);
249 lbl->set_link_color(conf->link_color);
250
251 DBG_GUI_G << "Window builder: placed label '" << id << "' with definition '"
252 << definition << "'.";
253
254 return lbl;
255}
256
257} // namespace implementation
258
259// }------------ END --------------
260
261} // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
@ yes_no_buttons
Shows a yes and no button.
Definition message.hpp:81
@ auto_close
Enables auto close.
Definition message.hpp:71
unsigned short text_alpha_
Definition label.hpp:159
virtual bool get_link_aware() const override
See styled_widget::get_link_aware.
Definition label.hpp:51
void signal_handler_left_button_click(bool &handled)
Left click signal handler: checks if we clicked on a hyperlink.
Definition label.cpp:115
void set_link_color(const color_t &color)
Definition label.cpp:98
void signal_handler_mouse_leave(bool &handled)
Mouse leave signal handler: checks if the cursor left a hyperlink.
Definition label.cpp:180
color_t link_color_
What color links will be rendered in.
Definition label.hpp:155
void signal_handler_right_button_click(bool &handled)
Right click signal handler: checks if we clicked on a hyperlink, copied to clipboard.
Definition label.cpp:145
bool link_aware_
Whether the label is link aware, rendering links with special formatting and handling click events.
Definition label.hpp:150
virtual void update_canvas() override
See styled_widget::update_canvas.
Definition label.cpp:63
void set_state(const state_t state)
Definition label.cpp:107
state_t
Possible states of the widget.
Definition label.hpp:121
virtual bool get_active() const override
See styled_widget::get_active.
Definition label.hpp:66
state_t state_
Current state of the widget.
Definition label.hpp:134
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition label.cpp:82
void update_mouse_cursor(bool enable)
Implementation detail for (re)setting the hyperlink cursor.
Definition label.cpp:194
void set_link_aware(bool l)
Definition label.cpp:89
void set_text_alpha(unsigned short alpha)
Definition label.cpp:73
void signal_handler_mouse_motion(bool &handled, const point &coordinate)
Mouse motion signal handler: checks if the cursor is on a hyperlink.
Definition label.cpp:167
std::string get_label_link(const point &position) const
virtual void update_canvas()
Updates the canvas(ses).
std::vector< canvas > & get_canvases()
void queue_redraw()
Indicates that this widget should be redrawn.
Definition widget.cpp:464
constexpr uint8_t ALPHA_OPAQUE
Definition color.hpp:37
const config * cfg
static std::string _(const char *str)
Definition gettext.hpp:100
Define the common log macros for the gui toolkit.
#define DBG_GUI_G
Definition log.hpp:41
#define DBG_GUI_P
Definition log.hpp:66
#define DBG_GUI_E
Definition log.hpp:35
std::string label
What to show in the filter's drop-down list.
Definition manager.cpp:201
CURSOR_TYPE get()
Definition cursor.cpp:185
@ NORMAL
Definition cursor.hpp:28
@ HYPERLINK
Definition cursor.hpp:28
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition cursor.cpp:151
void copy_to_clipboard(const std::string &text)
Copies text to the clipboard.
Definition clipboard.cpp:24
constexpr bool open_object_is_supported()
Returns whether open_object() is supported/implemented for the current platform.
Definition open.hpp:54
bool open_object(const std::string &path_or_url)
Opens the specified object with the default application configured for its type.
Definition open.cpp:50
Graphical text output.
Generic file dialog.
point get_mouse_position()
Returns the current mouse position.
Definition helper.cpp:167
PangoAlignment decode_text_alignment(const std::string &alignment)
Converts a text alignment string to a text alignment.
Definition helper.cpp:84
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
Definition message.cpp:148
@ OK
Dialog was closed with the OK button.
Definition retval.hpp:35
Contains the implementation details for lexical_cast and shouldn't be used directly.
Desktop environment interaction functions.
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
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 label.cpp:241
std::string definition
Parameters for the styled_widget.
resolution(const config &cfg)
Definition label.cpp:217
label_definition(const config &cfg)
Definition label.cpp:209
std::vector< state_definition > state
Holds a 2D point.
Definition point.hpp:25
std::string missing_mandatory_wml_tag(const std::string &section, const std::string &tag)
Returns a standard message for a missing wml child (tag).
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define VALIDATE_WML_CHILD(cfg, key, message)