The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
floating_textbox.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2006 - 2025
3 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
4 Copyright (C) 2003 by David White <dave@whitevine.net>
5 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY.
13
14 See the COPYING file for more details.
15*/
16
17#include "floating_textbox.hpp"
18
20#include "floating_label.hpp"
22#include "game_display.hpp"
24#include "video.hpp"
25#include "log.hpp"
26
27#include <SDL3/SDL_keyboard.h>
28#include <ctime>
29
30static lg::log_domain log_display("display");
31#define ERR_DP LOG_STREAM(err, log_display)
32
33namespace gui
34{
36 box_(nullptr),
37 check_(nullptr),
38 mode_(TEXTBOX_NONE),
39 label_string_(),
40 label_(0),
41 command_history_()
42{}
43
45{
46 if(!active()) {
47 return;
48 }
49
50 if(check_ != nullptr && mode_ == TEXTBOX_MESSAGE) {
52 }
53 box_.reset(nullptr);
54 check_.reset(nullptr);
57
58#if defined(__ANDROID__) || defined(__IPHONEOS__)
59 // Hide onscreen keyboard
60 SDL_StopTextInput(video::get_window());
61#endif
62}
63
65{
66 if(box_ == nullptr) {
67 return;
68 }
69
70 const rect& area = gui.map_outside_area();
71
72 const int border_size = 10;
73
74#ifdef __ANDROID__
75 // On Android the Onscreen keyboard hides this box if aligned to bottom,
76 // so we align it to top instead.
77 const int ypos = area.y + border_size - (check_ != nullptr ? check_->height() + border_size : 0);
78#else
79 const int ypos = area.y + area.h - 30 - (check_ != nullptr ? check_->height() + border_size : 0);
80#endif
81
82 if(label_ != 0) {
84 }
85
88 flabel.set_position(area.x + border_size, ypos);
90 flabel.set_clip_rect(area);
91
92 // This label should always be a single line and never wrap. Without explicitly setting -1, Pango
93 // will measure it against a full-screen-wide wrap box (floating label's clip_rect width), and for
94 // a pure RTL caption (eg Arabic, Hebrew) Pango inflates the measured width to practically the
95 // entire screen width - therefore there is no room for the text-box and it appears as though it
96 // doesn't work for RTL text. Refer GitHub #8673.
97 flabel.set_width(-1);
98
100
101 if(label_ == 0) {
102 return;
103 }
104
105 const rect& label_area = font::get_floating_label_rect(label_);
106 const int textbox_width = area.w - label_area.w - border_size * 3;
107
108 if(textbox_width <= 0) {
110 return;
111 }
112
113 if(box_ != nullptr) {
114 const rect rect {
115 area.x + label_area.w + border_size * 2
116 , ypos
117 , textbox_width
118 , box_->height()
119 };
120
121 box_->set_location(rect);
122 }
123
124 if(check_ != nullptr) {
125 check_->set_location(box_->location().x,box_->location().y + box_->location().h + border_size);
126 }
127}
128
130 gui::TEXTBOX_MODE mode, const std::string& label,
131 const std::string& check_label, bool checked, game_display& gui)
132{
133 close();
134
136 mode_ = mode;
137
138 if(!check_label.empty()) {
139 check_.reset(new gui::button(check_label,gui::button::TYPE_CHECK));
140 check_->set_check(checked);
141 }
142
143 box_.reset(new gui::textbox(100,"",true,256,font::SIZE_NORMAL,0.8,0.6));
144
146
147#if defined(__ANDROID__) || defined(__IPHONEOS__)
148 // Show onscreen keyboard
149 SDL_StartTextInput(video::get_window());
150#endif
151}
152
153void floating_textbox::tab(const std::set<std::string>& dictionary)
154{
155 if(active() == false) {
156 return;
157 }
158
159 std::string text = box_->text();
160 std::vector<std::string> matches(dictionary.begin(), dictionary.end());
161 const bool line_start = utils::word_completion(text, matches);
162
163 if(matches.empty()) {
164 return;
165 }
166
167 if(matches.size() == 1 && mode_ == gui::TEXTBOX_MESSAGE) {
168 text.append(line_start ? ": " : " ");
169 } else if(matches.size() > 1) {
170 std::string completion_list = utils::join(matches, " ");
172 std::chrono::system_clock::now(), "", 0, completion_list, events::chat_handler::MESSAGE_PRIVATE, false);
173 }
174 box_->set_text(text);
175}
176
177void floating_textbox::memorize_command(const std::string& command)
178{
179 if(command.empty()) {
180 return;
181 }
182
183 auto prev = std::find(command_history_.begin(), command_history_.end(), command);
184
185 if(prev != command_history_.end()) {
186 command_history_.erase(prev);
187 }
188 command_history_.emplace_back(command);
189}
190}
map_location prev
void add_chat_message(const std::chrono::system_clock::time_point &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
void set_position(double xpos, double ypos)
void set_alignment(ALIGN align)
void set_color(const color_t &color)
void set_clip_rect(const rect &r)
static game_display * get_singleton()
display_chat_manager & get_chat_manager()
void show(gui::TEXTBOX_MODE mode, const std::string &label, const std::string &check_label, bool checked, game_display &gui)
void memorize_command(const std::string &command)
TEXTBOX_MODE mode() const
void update_location(game_display &gui)
void tab(const std::set< std::string > &dictionary)
std::unique_ptr< gui::button > check_
std::vector< std::string > command_history_
std::unique_ptr< gui::textbox > box_
static prefs & get()
void set_message_private(bool value)
static lg::log_domain log_display("display")
std::string label
What to show in the filter's drop-down list.
Definition manager.cpp:201
Standard logging facilities (interface).
const color_t YELLOW_COLOR
int add_floating_label(const floating_label &flabel)
add a label floating on the screen above everything else.
rect get_floating_label_rect(int handle)
void remove_floating_label(int handle, const std::chrono::milliseconds &fadeout)
removes the floating label given by 'handle' from the screen
const int SIZE_NORMAL
Definition constants.cpp:20
General purpose widgets.
std::string join(const Range &v, const std::string &s=",")
Generates a new string joining container items in a list.
bool word_completion(std::string &text, std::vector< std::string > &wordlist)
Try to complete the last word of 'text' with the 'wordlist'.
SDL_Window * get_window()
Definition video.cpp:712
An abstract description of a rectangle with integer coordinates.
Definition rect.hpp:49