The Battle for Wesnoth  1.19.2+dev
scroll_text.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2023 - 2024
3  by babaissarkar(Subhraman Sarkar) <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 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
19 
24 #include "gettext.hpp"
25 #include "wml_exception.hpp"
26 
27 #include <functional>
28 
29 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
30 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
31 
32 namespace gui2
33 {
34 
35 // ------------ WIDGET -----------{
36 
37 REGISTER_WIDGET(scroll_text)
38 
39 scroll_text::scroll_text(const implementation::builder_scroll_text& builder)
40  : scrollbar_container(builder, type())
41  , state_(ENABLED)
42  , wrap_on_(false)
43  , text_alignment_(builder.text_alignment)
44  , editable_(true)
45  , max_size_(point(0,0))
46 {
47  connect_signal<event::LEFT_BUTTON_DOWN>(
48  std::bind(&scroll_text::signal_handler_left_button_down, this, std::placeholders::_2),
50 }
51 
53 {
54  if(content_grid()) {
55  return dynamic_cast<multiline_text*>(content_grid()->find("_text", false));
56  }
57 
58  return nullptr;
59 }
60 
62 {
64  widget->set_value(label);
65  widget->set_label(label);
66 
67  bool resize_needed = !content_resize_request();
68  if(resize_needed && get_size() != point()) {
70  }
71  widget->goto_start_of_data();
72  }
73 }
74 
76 {
78  return widget->get_value();
79  } else {
80  return "";
81  }
82 }
83 
84 void scroll_text::set_text_alignment(const PangoAlignment text_alignment)
85 {
86  // Inherit.
87  styled_widget::set_text_alignment(text_alignment);
88 
89  text_alignment_ = text_alignment;
90 
92  widget->set_text_alignment(text_alignment_);
93  }
94 }
95 
96 void scroll_text::set_use_markup(bool use_markup)
97 {
98  // Inherit.
100 
102  widget->set_use_markup(use_markup);
103  }
104 }
105 
106 void scroll_text::set_self_active(const bool active)
107 {
108  state_ = active ? ENABLED : DISABLED;
109 }
110 
112 {
113  return state_ != DISABLED;
114 }
115 
116 unsigned scroll_text::get_state() const
117 {
118  return state_;
119 }
120 
122 {
124  assert(text);
125 
126  text->set_editable(is_editable());
127  text->set_label(get_label());
130 }
131 
132 void scroll_text::place(const point& origin, const point& size) {
134 
136  const SDL_Rect& visible_area = content_visible_area();
137 
138  if (widget->get_cursor_pos().x < visible_area.w/2.0) {
140  } else {
141  scroll_horizontal_scrollbar_by(widget->get_cursor_pos().x - visible_area.w/2.0);
142  }
143 
144  if (widget->get_cursor_pos().y >= (widget->get_text_end_pos().y - visible_area.h/2.0)) {
145  if (widget->get_lines_count() > 1) {
147  } else {
149  }
150  } else if (widget->get_cursor_pos().y < visible_area.h/2.0) {
152  } else {
153  scroll_vertical_scrollbar_by(widget->get_cursor_pos().y - visible_area.h/2.0);
154  }
155 
156  if (widget->get_length() == 0) {
159  }
160 
161  set_max_size(widget->get_config_default_size());
162  }
163 }
164 
166 {
168 
169  if ((calc_size.x > max_size_.x) && (max_size_.x != 0)) {
170  calc_size.x = max_size_.x;
171  }
172 
173  if ((calc_size.y > max_size_.y) && (max_size_.y != 0)) {
174  calc_size.y = max_size_.y;
175  }
176 
177  return calc_size;
178 }
179 
181 {
182  // ------ get vertical scrollbar size ------
184  ? point()
186 
187  // ------ get horizontal scrollbar size ------
189  ? point()
191 
192  // padding = 3
193  max_size_ = point(max_size.x + vertical_scrollbar.x + 3, max_size.y + horizontal_scrollbar.y + 3);
194 }
195 
196 
197 
198 void scroll_text::set_can_wrap(bool can_wrap)
199 {
200  wrap_on_ = can_wrap;
201 }
202 
204 {
205  return true;
206 }
207 
209 {
210  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
211 
212  get_window()->keyboard_capture(this);
213 }
214 
215 // }---------- DEFINITION ---------{
216 
219 {
220  DBG_GUI_P << "Parsing scroll text " << id;
221 
222  load_resolutions<resolution>(cfg);
223 }
224 
226  : resolution_definition(cfg), grid(nullptr)
227 {
228  // Note the order should be the same as the enum state_t is scroll_text.hpp.
229  state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_enabled", missing_mandatory_wml_tag("scroll_text", "state_enabled")));
230  state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_disabled", missing_mandatory_wml_tag("scroll_text", "state_disabled")));
231 
232  auto child = VALIDATE_WML_CHILD(cfg, "grid", missing_mandatory_wml_tag("scroll_text", "grid"));
233  grid = std::make_shared<builder_grid>(child);
234 }
235 
236 // }---------- BUILDER -----------{
237 
238 namespace implementation
239 {
240 
241 builder_scroll_text::builder_scroll_text(const config& cfg)
243  , vertical_scrollbar_mode(get_scrollbar_mode(cfg["vertical_scrollbar_mode"]))
244  , horizontal_scrollbar_mode(get_scrollbar_mode(cfg["horizontal_scrollbar_mode"]))
245  , text_alignment(decode_text_alignment(cfg["text_alignment"]))
246  , editable(cfg["editable"].to_bool(true))
247 {
248  // Scrollbar default to auto. AUTO_VISIBLE_FIRST_RUN doesn't work.
251  }
252 
255  }
256 }
257 
258 std::unique_ptr<widget> builder_scroll_text::build() const
259 {
260  auto widget = std::make_unique<scroll_text>(*this);
261 
262  widget->set_vertical_scrollbar_mode(vertical_scrollbar_mode);
263  widget->set_horizontal_scrollbar_mode(horizontal_scrollbar_mode);
264  widget->set_editable(editable);
265  widget->set_text_alignment(text_alignment);
266 
267  const auto conf = widget->cast_config_to<scroll_text_definition>();
268  assert(conf);
269 
270  widget->init_grid(*conf->grid);
271  widget->finalize_setup();
272 
273  DBG_GUI_G << "Window builder: placed scroll text '" << id
274  << "' with definition '" << definition << "'.";
275 
276  return widget;
277 }
278 
279 } // namespace implementation
280 
281 // }------------ END --------------
282 
283 } // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
Base container class.
Definition: grid.hpp:32
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Definition: grid.cpp:645
void set_max_size(point max_size)
Sets the size of the text beyond which scrollbars should be visible.
void signal_handler_left_button_down(const event::ui_event event)
virtual unsigned get_state() const override
See styled_widget::get_state.
std::string get_value()
Definition: scroll_text.cpp:75
multiline_text * get_internal_text_box()
Definition: scroll_text.cpp:52
PangoAlignment text_alignment_
void set_can_wrap(bool can_wrap)
void finalize_subclass() override
Function for the subclasses to do their setup.
virtual void set_label(const t_string &label) override
Definition: scroll_text.cpp:61
virtual void set_self_active(const bool active) override
See container_base::set_self_active.
void place(const point &origin, const point &size) override
See widget::place.
point calculate_best_size() const override
See widget::calculate_best_size.
virtual bool get_active() const override
See styled_widget::get_active.
state_t state_
Current state of the widget.
virtual void set_use_markup(bool use_markup) override
See styled_widget::set_use_markup.
Definition: scroll_text.cpp:96
virtual void set_text_alignment(const PangoAlignment text_alignment) override
See styled_widget::set_text_alignment.
Definition: scroll_text.cpp:84
bool can_wrap() const override
See widget::can_wrap.
@ END
Go to the end position.
Definition: scrollbar.hpp:58
@ BEGIN
Go to begin position.
Definition: scrollbar.hpp:53
Base class for creating containers with one or two scrollbar(s).
void scroll_vertical_scrollbar(const scrollbar_base::scroll_mode scroll)
Scrolls the vertical scrollbar.
@ AUTO_VISIBLE_FIRST_RUN
Like AUTO_VISIBLE, but when not needed upon the initial layout phase, the bars are not shown and no s...
@ AUTO_VISIBLE
The scrollbar is shown when the number of items is larger as the visible items.
virtual void place(const point &origin, const point &size) override
See widget::place.
void scroll_horizontal_scrollbar(const scrollbar_base::scroll_mode scroll)
Scrolls the horizontal scrollbar.
virtual point calculate_best_size() const override
See widget::calculate_best_size.
void scroll_horizontal_scrollbar_by(const int pixels)
Scrolls the horizontal scrollbar by pixel.
bool content_resize_request(const bool force_sizing=false)
Notification if the content of a child needs a resize.
const SDL_Rect & content_visible_area() const
void scroll_vertical_scrollbar_by(const int pixels)
Scrolls the vertical scrollbar by pixel.
const t_string & get_label() const
virtual void set_text_alignment(const PangoAlignment text_alignment)
virtual void set_label(const t_string &text)
virtual void set_use_markup(bool use_markup)
bool get_use_markup() const
void set_editable(bool editable)
Set or unset whether text can be edited or not Text can only be copied and scrolled through when edit...
Base class for all widgets.
Definition: widget.hpp:53
point get_best_size() const
Gets the best size for the widget.
Definition: widget.cpp:193
visibility get_visible() const
Definition: widget.cpp:496
point get_origin() const
Returns the screen origin of the widget.
Definition: widget.cpp:301
point get_size() const
Returns the size of the widget.
Definition: widget.cpp:306
window * get_window()
Get the parent window.
Definition: widget.cpp:117
@ invisible
The user set the widget invisible, that means:
void keyboard_capture(widget *widget)
Definition: window.cpp:1221
#define DBG_GUI_G
Definition: log.hpp:41
#define DBG_GUI_P
Definition: log.hpp:66
#define DBG_GUI_E
Definition: log.hpp:35
void point(int x, int y)
Draw a single point.
Definition: draw.cpp:202
ui_event
The event sent to the dispatcher.
Definition: handler.hpp:115
scrollbar_mode get_scrollbar_mode(const std::string &scrollbar_mode)
Returns the scrollbar mode flags.
Definition: helper.cpp:121
Generic file dialog.
PangoAlignment decode_text_alignment(const std::string &alignment)
Converts a text alignment string to a text alignment.
Definition: helper.cpp:94
Contains the implementation details for lexical_cast and shouldn't be used directly.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:85
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
#define LOG_HEADER
Definition: scroll_text.cpp:30
scrollbar_container::scrollbar_mode horizontal_scrollbar_mode
scrollbar_container::scrollbar_mode vertical_scrollbar_mode
virtual std::unique_ptr< widget > build() const override
std::string definition
Parameters for the styled_widget.
std::vector< state_definition > state
scroll_text_definition(const config &cfg)
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)