The Battle for Wesnoth  1.19.0-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  }
72 }
73 
75 {
77  return widget->get_value();
78  } else {
79  return "";
80  }
81 }
82 
83 void scroll_text::set_text_alignment(const PangoAlignment text_alignment)
84 {
85  // Inherit.
86  styled_widget::set_text_alignment(text_alignment);
87 
88  text_alignment_ = text_alignment;
89 
91  widget->set_text_alignment(text_alignment_);
92  }
93 }
94 
95 void scroll_text::set_use_markup(bool use_markup)
96 {
97  // Inherit.
99 
101  widget->set_use_markup(use_markup);
102  }
103 }
104 
105 void scroll_text::set_self_active(const bool active)
106 {
107  state_ = active ? ENABLED : DISABLED;
108 }
109 
111 {
112  return state_ != DISABLED;
113 }
114 
115 unsigned scroll_text::get_state() const
116 {
117  return state_;
118 }
119 
121 {
123  assert(text);
124 
125  text->set_editable(is_editable());
126  text->set_label(get_label());
129 }
130 
131 void scroll_text::place(const point& origin, const point& size) {
133 
135  const SDL_Rect& visible_area = content_visible_area();
136 
137  if (widget->get_cursor_pos().x < visible_area.w/2.0) {
139  } else {
140  scroll_horizontal_scrollbar_by(widget->get_cursor_pos().x - visible_area.w/2.0);
141  }
142 
143  if (widget->get_cursor_pos().y >= (widget->get_text_end_pos().y - visible_area.h/2.0)) {
144  if (widget->get_lines_count() > 1) {
146  } else {
148  }
149  } else if (widget->get_cursor_pos().y < visible_area.h/2.0) {
151  } else {
152  scroll_vertical_scrollbar_by(widget->get_cursor_pos().y - visible_area.h/2.0);
153  }
154 
155  if (widget->get_length() == 0) {
158  }
159 
160  set_max_size(widget->get_config_default_size());
161  }
162 }
163 
165 {
167 
168  if ((calc_size.x > max_size_.x) && (max_size_.x != 0)) {
169  calc_size.x = max_size_.x;
170  }
171 
172  if ((calc_size.y > max_size_.y) && (max_size_.y != 0)) {
173  calc_size.y = max_size_.y;
174  }
175 
176  return calc_size;
177 }
178 
180 {
181  // ------ get vertical scrollbar size ------
183  ? point()
185 
186  // ------ get horizontal scrollbar size ------
188  ? point()
190 
191  // padding = 3
192  max_size_ = point(max_size.x + vertical_scrollbar.x + 3, max_size.y + horizontal_scrollbar.y + 3);
193 }
194 
195 
196 
197 void scroll_text::set_can_wrap(bool can_wrap)
198 {
199  wrap_on_ = can_wrap;
200 }
201 
203 {
204  return true;
205 }
206 
208 {
209  DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
210 
211  get_window()->keyboard_capture(this);
212 }
213 
214 // }---------- DEFINITION ---------{
215 
218 {
219  DBG_GUI_P << "Parsing scroll text " << id;
220 
221  load_resolutions<resolution>(cfg);
222 }
223 
225  : resolution_definition(cfg), grid(nullptr)
226 {
227  // Note the order should be the same as the enum state_t is scroll_text.hpp.
228  state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_enabled", missing_mandatory_wml_tag("scroll_text", "state_enabled")));
229  state.emplace_back(VALIDATE_WML_CHILD(cfg, "state_disabled", missing_mandatory_wml_tag("scroll_text", "state_disabled")));
230 
231  auto child = VALIDATE_WML_CHILD(cfg, "grid", missing_mandatory_wml_tag("scroll_text", "grid"));
232  grid = std::make_shared<builder_grid>(child);
233 }
234 
235 // }---------- BUILDER -----------{
236 
237 namespace implementation
238 {
239 
240 builder_scroll_text::builder_scroll_text(const config& cfg)
242  , vertical_scrollbar_mode(get_scrollbar_mode(cfg["vertical_scrollbar_mode"]))
243  , horizontal_scrollbar_mode(get_scrollbar_mode(cfg["horizontal_scrollbar_mode"]))
244  , text_alignment(decode_text_alignment(cfg["text_alignment"]))
245  , editable(cfg["editable"].to_bool(true))
246 {
247  // Scrollbar default to auto. AUTO_VISIBLE_FIRST_RUN doesn't work.
250  }
251 
254  }
255 }
256 
257 std::unique_ptr<widget> builder_scroll_text::build() const
258 {
259  auto widget = std::make_unique<scroll_text>(*this);
260 
261  widget->set_vertical_scrollbar_mode(vertical_scrollbar_mode);
262  widget->set_horizontal_scrollbar_mode(horizontal_scrollbar_mode);
263  widget->set_editable(editable);
264  widget->set_text_alignment(text_alignment);
265 
266  const auto conf = widget->cast_config_to<scroll_text_definition>();
267  assert(conf);
268 
269  widget->init_grid(*conf->grid);
270  widget->finalize_setup();
271 
272  DBG_GUI_G << "Window builder: placed scroll text '" << id
273  << "' with definition '" << definition << "'.";
274 
275  return widget;
276 }
277 
278 } // namespace implementation
279 
280 // }------------ END --------------
281 
282 } // 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
A horizontal scrollbar is a widget that shows a horizontal scrollbar.
A label displays text that can be wrapped but no scrollbars are provided.
Definition: label.hpp:56
Base class for a multiline text area.
Scrollable text area.
Definition: scroll_text.hpp:69
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:74
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:95
virtual void set_text_alignment(const PangoAlignment text_alignment) override
See styled_widget::set_text_alignment.
Definition: scroll_text.cpp:83
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)
The definition of a vertical scrollbar.
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:497
point get_origin() const
Returns the screen origin of the widget.
Definition: widget.cpp:302
point get_size() const
Returns the size of the widget.
Definition: widget.cpp:307
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:58
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.
Base class of a resolution, contains the common keys for a resolution.
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)