The Battle for Wesnoth  1.19.15+dev
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 
19 #include "display_chat_manager.hpp"
20 #include "floating_label.hpp"
21 #include "font/standard_colors.hpp"
22 #include "game_display.hpp"
24 #include "log.hpp"
25 
26 #include <SDL2/SDL_keyboard.h>
27 #include <ctime>
28 
29 static lg::log_domain log_display("display");
30 #define ERR_DP LOG_STREAM(err, log_display)
31 
32 namespace gui
33 {
35  box_(nullptr),
36  check_(nullptr),
37  mode_(TEXTBOX_NONE),
38  label_string_(),
39  label_(0),
40  command_history_()
41 {}
42 
44 {
45  if(!active()) {
46  return;
47  }
48 
49  if(check_ != nullptr && mode_ == TEXTBOX_MESSAGE) {
51  }
52  box_.reset(nullptr);
53  check_.reset(nullptr);
56 
57 #ifdef __ANDROID__
58  // Hide onscreen keyboard
59  SDL_StopTextInput();
60 #endif
61 }
62 
64 {
65  if(box_ == nullptr) {
66  return;
67  }
68 
69  const rect& area = gui.map_outside_area();
70 
71  const int border_size = 10;
72 
73 #ifdef __ANDROID__
74  // On Android the Onscreen keyboard hides this box if aligned to bottom,
75  // so we align it to top instead.
76  const int ypos = area.y + border_size - (check_ != nullptr ? check_->height() + border_size : 0);
77 #else
78  const int ypos = area.y + area.h - 30 - (check_ != nullptr ? check_->height() + border_size : 0);
79 #endif
80 
81  if(label_ != 0) {
83  }
84 
87  flabel.set_position(area.x + border_size, ypos);
89  flabel.set_clip_rect(area);
90 
92 
93  if(label_ == 0) {
94  return;
95  }
96 
97  const rect& label_area = font::get_floating_label_rect(label_);
98  const int textbox_width = area.w - label_area.w - border_size * 3;
99 
100  if(textbox_width <= 0) {
102  return;
103  }
104 
105  if(box_ != nullptr) {
106  const rect rect {
107  area.x + label_area.w + border_size * 2
108  , ypos
109  , textbox_width
110  , box_->height()
111  };
112 
113  box_->set_location(rect);
114  }
115 
116  if(check_ != nullptr) {
117  check_->set_location(box_->location().x,box_->location().y + box_->location().h + border_size);
118  }
119 }
120 
122  gui::TEXTBOX_MODE mode, const std::string& label,
123  const std::string& check_label, bool checked, game_display& gui)
124 {
125  close();
126 
128  mode_ = mode;
129 
130  if(!check_label.empty()) {
131  check_.reset(new gui::button(check_label,gui::button::TYPE_CHECK));
132  check_->set_check(checked);
133  }
134 
135  box_.reset(new gui::textbox(100,"",true,256,font::SIZE_NORMAL,0.8,0.6));
136 
138 
139 #ifdef __ANDROID__
140  // Show onscreen keyboard
141  SDL_StartTextInput();
142 #endif
143 }
144 
145 void floating_textbox::tab(const std::set<std::string>& dictionary)
146 {
147  if(active() == false) {
148  return;
149  }
150 
151  std::string text = box_->text();
152  std::vector<std::string> matches(dictionary.begin(), dictionary.end());
153  const bool line_start = utils::word_completion(text, matches);
154 
155  if(matches.empty()) {
156  return;
157  }
158 
159  if(matches.size() == 1 && mode_ == gui::TEXTBOX_MESSAGE) {
160  text.append(line_start ? ": " : " ");
161  } else if(matches.size() > 1) {
162  std::string completion_list = utils::join(matches, " ");
164  std::chrono::system_clock::now(), "", 0, completion_list, events::chat_handler::MESSAGE_PRIVATE, false);
165  }
166  box_->set_text(text);
167 }
168 
169 void floating_textbox::memorize_command(const std::string& command)
170 {
171  if(command.empty()) {
172  return;
173  }
174 
175  auto prev = std::find(command_history_.begin(), command_history_.end(), command);
176 
177  if(prev != command_history_.end()) {
178  command_history_.erase(prev);
179  }
180  command_history_.emplace_back(command);
181 }
182 }
map_location prev
Definition: astarsearch.cpp:64
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()
@ TYPE_CHECK
Definition: button.hpp:29
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.
@ TEXTBOX_MESSAGE
std::string join(const T &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'.
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
Definition: general.hpp:141
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:49