The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
chatbox.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 - 2025
3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY.
11
12 See the COPYING file for more details.
13*/
14
15#define GETTEXT_DOMAIN "wesnoth-lib"
16
18
21#include "gui/widgets/image.hpp"
27
28#include "font/pango/escape.hpp"
29#include "formatter.hpp"
32#include "gettext.hpp"
33#include "log.hpp"
37#include "wml_exception.hpp"
38
39static lg::log_domain log_lobby("lobby");
40#define DBG_LB LOG_STREAM(debug, log_lobby)
41#define LOG_LB LOG_STREAM(info, log_lobby)
42#define ERR_LB LOG_STREAM(err, log_lobby)
43
44#define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
45#define LOG_HEADER LOG_SCOPE_HEADER + ':'
46
47namespace gui2
48{
49
50// ------------ WIDGET -----------{
51
52REGISTER_WIDGET(chatbox)
53
54chatbox::chatbox(const implementation::builder_chatbox& builder)
55 : container_base(builder, type())
56 , roomlistbox_(nullptr)
57 , chat_log_container_(nullptr)
58 , chat_input_(nullptr)
59 , active_window_(0)
60 , active_window_changed_callback_()
61 , log_(nullptr)
62{
63 // We only implement a RECEIVE_KEYBOARD_FOCUS handler; LOSE_KEYBOARD_FOCUS
64 // isn't needed. This handler forwards focus to the input textbox, meaning
65 // if keyboard_focus is called on a chatbox, distributor::keyboard_focus_
66 // will immediately be set to the input textbox, which will then handle focus
67 // loss itself when applicable. Nothing else happens in the interim while
68 // keyboard_focus_ equals `this` to warrent cleanup.
69 connect_signal<event::RECEIVE_KEYBOARD_FOCUS>(
70 std::bind(&chatbox::signal_handler_receive_keyboard_focus, this, std::placeholders::_2));
71}
72
74{
75 roomlistbox_ = find_widget<listbox>("room_list", false, true);
76
77 // We need to bind a lambda here since switch_to_window is overloaded.
78 // A lambda alone would be more verbose because it'd need to specify all the parameters.
79 connect_signal_notify_modified(*roomlistbox_,
80 [this](auto&&...) { switch_to_window(roomlistbox_->get_selected_row()); });
81
82 chat_log_container_ = find_widget<multi_page>("chat_log_container", false, true);
83
84 chat_input_ = find_widget<text_box>("chat_input", false, true);
85
86 connect_signal_pre_key_press(*chat_input_,
87 std::bind(&chatbox::chat_input_keypress_callback, this, std::placeholders::_5));
88}
89
90void chatbox::load_log(std::map<std::string, chatroom_log>& log, bool show_lobby)
91{
92 const std::string new_tip = formatter()
93 << "\n"
94 // TRANSLATORS: This is the new chat text indicator
95 << markup::span_color("#FF0000", "============", _("NEW"), "============");
96
97 for(auto& l : log) {
98 const bool is_lobby = l.first == "lobby";
99
100 if(!show_lobby && is_lobby && !l.second.whisper) {
101 continue;
102 }
103
104 const std::size_t new_tip_index = l.second.log.find(new_tip);
105
106 if(new_tip_index != std::string::npos) {
107 l.second.log.replace(new_tip_index, new_tip.length(), "");
108 }
109 find_or_create_window(l.first, l.second.whisper, true, !is_lobby, l.second.log + new_tip);
110 }
111
112 log_ = &log;
113}
114
116{
118
119 // Clear pending messages notification in room listbox
122
123 t.pending_messages = 0;
124
127 }
128}
129
134
135void chatbox::switch_to_window(std::size_t id)
136{
138 assert(active_window_ < open_windows_.size());
139
142
143 // Grab input focus
145
147}
148
149void chatbox::chat_input_keypress_callback(const SDL_Keycode key)
150{
151 std::string input = chat_input_->get_value();
152 if(input.empty() || chat_input_->is_composing()) {
153 return;
154 }
155
157
158 switch(key) {
159 case SDLK_RETURN:
160 case SDLK_KP_ENTER: {
161 if(input[0] == '/') {
162 // TODO: refactor do_speak so it uses context information about
163 // opened window, so e.g. /ignore in a whisper session ignores
164 // the other party without having to specify it's nick.
165 chat_handler::do_speak(input);
166 } else {
167 if(t.whisper) {
168 send_whisper(t.name, input);
169 add_whisper_sent(t.name, input);
170 } else {
171 send_chat_room_message(t.name, input);
172 add_chat_room_message_sent(t.name, input);
173 }
174 }
175
178
179 break;
180 }
181
182 case SDLK_TAB: {
183 auto* li = mp::get_lobby_info();
184 if(!li) {
185 break;
186 }
187
188 std::vector<std::string> matches;
189 for(const auto& ui : li->users()) {
190 if(ui.name != prefs::get().login()) {
191 matches.push_back(ui.name);
192 }
193 }
194
195 const bool line_start = utils::word_completion(input, matches);
196
197 if(matches.empty()) {
198 return;
199 }
200
201 if(matches.size() == 1) {
202 input.append(line_start ? ": " : " ");
203 } else {
204 std::string completion_list = utils::join(matches, " ");
205 append_to_chatbox(completion_list);
206 }
207
208 chat_input_->set_value(input);
209
210 break;
211 }
212
213 default:
214 break;
215 }
216}
217
218void chatbox::append_to_chatbox(const std::string& text, const bool force_scroll)
219{
220 append_to_chatbox(text, active_window_, force_scroll);
221}
222
223void chatbox::append_to_chatbox(const std::string& text, std::size_t id, const bool force_scroll)
224{
226 scroll_text& log = grid.find_widget<scroll_text>("log_text");
227
228 const bool chatbox_at_end = log.vertical_scrollbar_at_end();
229 const unsigned chatbox_position = log.get_vertical_scrollbar_item_position();
230
231 const std::string before_message = log.get_value().empty() ? "" : "\n";
232 const std::string new_text = formatter()
233 << log.get_value() << before_message << markup::span_color("#bcb088", prefs::get().get_chat_timestamp(std::chrono::system_clock::now()), text);
234
235 log.set_use_markup(true);
236 log.set_value(new_text);
237
238 if(log_ != nullptr) {
239 try {
240 const std::string& room_name = open_windows_[id].name;
241 log_->at(room_name).log = new_text;
242 } catch(const std::out_of_range&) {
243 }
244 }
245
246 if(chatbox_at_end || force_scroll) {
248 } else {
249 log.set_vertical_scrollbar_item_position(chatbox_position);
250 }
251}
252
253void chatbox::send_chat_message(const std::string& message, bool /*allies_only*/)
254{
255 add_chat_message(std::chrono::system_clock::now(), prefs::get().login(), 0, message);
256 send_to_server(::config{"message", ::config{"message", message, "sender", prefs::get().login()}});
257}
258
260{
261 const auto id = active_window_;
263 scroll_text& log = grid.find_widget<scroll_text>("log_text");
264 log.set_label("");
265}
266
267void chatbox::user_relation_changed(const std::string& /*name*/)
268{
271 }
272}
273
274void chatbox::add_chat_message(const std::chrono::system_clock::time_point& /*time*/,
275 const std::string& speaker,
276 int /*side*/,
277 const std::string& message,
279{
280 std::string text;
281 if(message.compare(0, 4, "/me ") == 0) {
282 text = formatter() << markup::italic(speaker, " ", font::escape_text(message.substr(4)));
283 } else {
284 text = formatter() << markup::bold(speaker, ":") << font::escape_text(message);
285 }
286
287 append_to_chatbox(text);
288}
289
290void chatbox::add_whisper_sent(const std::string& receiver, const std::string& message)
291{
292 if(whisper_window_active(receiver)) {
294 } else if(lobby_chat_window* t = whisper_window_open(receiver, prefs::get().auto_open_whisper_windows())) {
297 } else {
298 add_active_window_whisper(VGETTEXT("whisper to $receiver", {{"receiver", receiver}}), message, true);
299 }
300}
301
302void chatbox::add_whisper_received(const std::string& sender, const std::string& message)
303{
304 bool can_go_to_active = !prefs::get().lobby_whisper_friends_only() || prefs::get().is_friend(sender);
305 bool can_open_new = prefs::get().auto_open_whisper_windows() && can_go_to_active;
306
307 if(whisper_window_open(sender, can_open_new)) {
308 if(whisper_window_active(sender)) {
310
311 do_notify(mp::notify_mode::whisper, sender, message);
312 } else {
315
317 }
318 } else if(can_go_to_active) {
320 do_notify(mp::notify_mode::whisper, sender, message);
321 } else {
322 LOG_LB << "Ignoring whisper from " << sender;
323 }
324}
325
326void chatbox::add_chat_room_message_sent(const std::string& room, const std::string& message)
327{
328 lobby_chat_window* t = room_window_open(room, false);
329 if(!t) {
330 LOG_LB << "Cannot add sent message to ui for room " << room << ", player not in the room";
331 return;
332 }
333
334 if(!room_window_active(room)) {
336 }
337
339}
340
341void chatbox::add_chat_room_message_received(const std::string& room,
342 const std::string& speaker,
343 const std::string& message)
344{
346
347 if(room_window_active(room)) {
349 notify_mode = mp::notify_mode::message;
350 } else {
351 add_room_window_message(room, speaker, message);
354 }
355
356 if(speaker == "server") {
358 } else if (utils::word_match(message, prefs::get().login())) {
359 notify_mode = mp::notify_mode::own_nick;
360 } else if (prefs::get().is_friend(speaker)) {
362 }
363
364 do_notify(notify_mode, speaker, message);
365}
366
367bool chatbox::whisper_window_active(const std::string& name)
368{
370 return t.name == name && t.whisper == true;
371}
372
373bool chatbox::room_window_active(const std::string& room)
374{
376 return t.name == room && t.whisper == false;
377}
378
379lobby_chat_window* chatbox::room_window_open(const std::string& room, const bool open_new, const bool allow_close)
380{
381 return find_or_create_window(room, false, open_new, allow_close,
382 VGETTEXT("Joined <i>$name</i>", { { "name", translation::dsgettext("wesnoth-lib", room.c_str()) } }));
383}
384
385lobby_chat_window* chatbox::whisper_window_open(const std::string& name, bool open_new)
386{
387 return find_or_create_window(name, true, open_new, true,
388 VGETTEXT("Started private message with <i>$name</i>. "
389 "If you do not want to receive messages from this player, type <i>/ignore $name</i>", { { "name", name } }));
390}
391
393 const bool whisper,
394 const bool open_new,
395 const bool allow_close,
396 const std::string& initial_text)
397{
398 for(auto& t : open_windows_) {
399 if(t.name == name && t.whisper == whisper) {
400 return &t;
401 }
402 }
403
404 if(!open_new) {
405 return nullptr;
406 }
407
408 open_windows_.emplace_back(name, whisper);
409
410 //
411 // Add a new chat log page.
412 //
413 widget_item item;
414 item["use_markup"] = "true";
415 item["label"] = initial_text;
416 widget_data data{{"log_text", item}};
417
418 if(log_ != nullptr) {
419 log_->emplace(name, chatroom_log{item["label"], whisper});
420 }
421
423
424 //
425 // Add a new room window tab.
426 //
427 data.clear();
428 item.clear();
429
430 if(!whisper) {
431 item["label"] = translation::dsgettext("wesnoth-lib", name.c_str());
432 } else {
433 item["label"] = "<" + name + ">";
434 }
435
436 data.emplace("room", item);
437
438 grid& row_grid = roomlistbox_->add_row(data);
439
440 //
441 // Set up the Close Window button.
442 //
443 button& close_button = row_grid.find_widget<button>("close_window");
444
445 if(!allow_close) {
447 } else {
448 connect_signal_mouse_left_click(close_button,
449 std::bind(&chatbox::close_window_button_callback, this, open_windows_.back().name, std::placeholders::_3, std::placeholders::_4));
450 }
451
452 return &open_windows_.back();
453}
454
455void chatbox::close_window_button_callback(const std::string& room_name, bool& handled, bool& halt)
456{
457 close_window(std::distance(open_windows_.begin(),
459
460 handled = halt = true;
461}
462
463void chatbox::send_to_server(const ::config& cfg)
464{
466}
467
468void chatbox::increment_waiting_whispers(const std::string& name)
469{
470 if(lobby_chat_window* t = whisper_window_open(name, false)) {
471 ++t->pending_messages;
472
473 if(t->pending_messages == 1) {
474 DBG_LB << "do whisper pending mark row " << (t - &open_windows_[0]) << " with " << t->name;
475
478 }
479 }
480}
481
482void chatbox::increment_waiting_messages(const std::string& room)
483{
484 if(lobby_chat_window* t = room_window_open(room, false)) {
485 ++t->pending_messages;
486
487 if(t->pending_messages == 1) {
488 int idx = t - &open_windows_[0];
489
490 DBG_LB << "do room pending mark row " << idx << " with " << t->name;
491
494 }
495 }
496}
497
498void chatbox::add_whisper_window_whisper(const std::string& sender, const std::string& message)
499{
500 lobby_chat_window* t = whisper_window_open(sender, false);
501 if(!t) {
502 ERR_LB << "Whisper window not open in add_whisper_window_whisper for " << sender;
503 return;
504 }
505
506 const std::string text = formatter() << markup::bold(sender, ": ") << font::escape_text(message);
507 append_to_chatbox(text, t - &open_windows_[0], false);
508}
509
510void chatbox::add_active_window_whisper(const std::string& sender,
511 const std::string& message,
512 const bool force_scroll)
513{
514 const std::string text = formatter() << markup::bold("whisper: ", sender, ": ") << font::escape_text(message);
515 append_to_chatbox(text, force_scroll);
516}
517
518void chatbox::close_window(std::size_t idx)
519{
520 const lobby_chat_window& t = open_windows_[idx];
521
522 DBG_LB << "Close window " << idx << " - " << t.name;
523
524 // Can't close the lobby!
525 if((t.name == "lobby" && t.whisper == false) || open_windows_.size() == 1) {
526 return;
527 }
528
529 // Check if we're closing the currently-active window.
530 const bool active_changed = idx == active_window_;
531
532 if(active_window_ == open_windows_.size() - 1) {
534 }
535
536 if(log_ != nullptr) {
537 log_->erase(t.name);
538 }
539
540 open_windows_.erase(open_windows_.begin() + idx);
541
544
547
548 if(active_changed) {
550 }
551}
552
553void chatbox::add_room_window_message(const std::string& room,
554 const std::string& sender,
555 const std::string& message)
556{
557 lobby_chat_window* t = room_window_open(room, false);
558 if(!t) {
559 ERR_LB << "Room window not open in add_room_window_message for " << room;
560 return;
561 }
562
563 const std::string text = formatter() << markup::bold(sender, ": ") << font::escape_text(message);
564 append_to_chatbox(text, t - &open_windows_[0], false);
565}
566
567void chatbox::add_active_window_message(const std::string& sender,
568 const std::string& message,
569 const bool force_scroll)
570{
571 const std::string text = formatter() << markup::bold(sender, ": ") << font::escape_text(message);
572 append_to_chatbox(text, force_scroll);
573}
574
575void chatbox::process_message(const ::config& data, bool whisper /*= false*/)
576{
577 std::string sender = data["sender"];
578 DBG_LB << "process message from " << sender << " " << (whisper ? "(w)" : "")
579 << ", len " << data["message"].str().size();
580
581 if(prefs::get().is_ignored(sender)) {
582 return;
583 }
584
585 const std::string& message = data["message"];
586 //prefs::get().parse_admin_authentication(sender, message); TODO: replace
587
588 if(whisper) {
590 } else {
591 if (!prefs::get().parse_should_show_lobby_join(sender, message)) return;
592
593 std::string room = data["room"];
594
595 // Attempt to send to the currently active room first.
596 if(room.empty()) {
597 LOG_LB << "Message without a room from " << sender << ", falling back to active window";
598 room = open_windows_[active_window_].name;
599 }
600
601 // If we still don't have a name, fall back to lobby.
602 if(room.empty()) {
603 LOG_LB << "Message without a room from " << sender << ", assuming lobby";
604 room = "lobby";
605 }
606
607 if(log_ != nullptr && data["type"].str() == "motd") {
608 if(log_->at("lobby").received_motd == message) {
609 LOG_LB << "Ignoring repeated motd";
610 return;
611 } else {
612 log_->at("lobby").received_motd = message;
613 }
614 }
615
617 }
618
619 // Notify plugins about the message
620 ::config plugin_data = data;
621 plugin_data["whisper"] = whisper;
622 plugins_manager::get()->notify_event("chat", plugin_data);
623}
624
626{
627 if(const auto message = data.optional_child("message")) {
629 } else if(const auto whisper = data.optional_child("whisper")) {
630 process_message(*whisper, true);
631 }
632}
633
635{
636 DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
637
638 // Forward focus to the input textbox.
640}
641
642// }---------- DEFINITION ---------{
643
646{
647 load_resolutions<resolution>(cfg);
648}
649
652{
653 state.emplace_back(VALIDATE_WML_CHILD(cfg, "background", missing_mandatory_wml_tag("chatbox_definition][resolution", "background")));
654 state.emplace_back(VALIDATE_WML_CHILD(cfg, "foreground", missing_mandatory_wml_tag("chatbox_definition][resolution", "foreground")));
655
656 auto child = VALIDATE_WML_CHILD(cfg, "grid", missing_mandatory_wml_tag("chatbox_definition][resolution", "grid"));
657 grid = std::make_shared<builder_grid>(child);
658}
659// }---------- BUILDER -----------{
660
661namespace implementation
662{
663
664builder_chatbox::builder_chatbox(const config& cfg)
666{
667}
668
669std::unique_ptr<widget> builder_chatbox::build() const
670{
671 auto widget = std::make_unique<chatbox>(*this);
672
673 DBG_GUI_G << "Window builder: placed unit preview pane '" << id
674 << "' with definition '" << definition << "'.";
675
676 const auto conf = widget->cast_config_to<chatbox_definition>();
677 assert(conf);
678
679 widget->init_grid(*conf->grid);
680 widget->finalize_setup();
681
682 return widget;
683}
684
685} // namespace implementation
686
687// }------------ END --------------
688
689} // namespace gui2
double t
static lg::log_domain log_lobby("lobby")
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
virtual void send_chat_room_message(const std::string &room, const std::string &message)
virtual void send_whisper(const std::string &receiver, const std::string &message)
std::ostringstream wrapper.
Definition formatter.hpp:40
Simple push button.
Definition button.hpp:36
std::map< std::string, chatroom_log > * log_
Definition chatbox.hpp:136
bool room_window_active(const std::string &room)
Definition chatbox.cpp:373
lobby_chat_window * room_window_open(const std::string &room, const bool open_new, const bool allow_close=true)
Check if a room window for "room" is open, if open_new is true then it will be created if not found.
Definition chatbox.cpp:379
text_box * chat_input_
Definition chatbox.hpp:128
lobby_chat_window * find_or_create_window(const std::string &name, const bool whisper, const bool open_new, const bool allow_close, const std::string &initial_text)
Helper function to find and open a new window, used by *_window_open.
Definition chatbox.cpp:392
virtual void clear_messages() override
Definition chatbox.cpp:259
void add_active_window_whisper(const std::string &sender, const std::string &message, const bool force_scroll=false)
Add a whisper message to the current window which is not the whisper window for "name".
Definition chatbox.cpp:510
void append_to_chatbox(const std::string &text, const bool force_scroll=false)
Definition chatbox.cpp:218
virtual void user_relation_changed(const std::string &name) override
Inherited form chat_handler.
Definition chatbox.cpp:267
virtual void send_chat_message(const std::string &message, bool allies_only) override
Inherited form chat_handler.
Definition chatbox.cpp:253
void add_active_window_message(const std::string &sender, const std::string &message, const bool force_scroll=false)
Add a message to the window for room "room".
Definition chatbox.cpp:567
void close_window(std::size_t idx)
Definition chatbox.cpp:518
void add_whisper_window_whisper(const std::string &sender, const std::string &message)
Add a whisper message to the whisper window.
Definition chatbox.cpp:498
virtual void add_chat_room_message_sent(const std::string &room, const std::string &message) override
Inherited form chat_handler.
Definition chatbox.cpp:326
multi_page * chat_log_container_
Definition chatbox.hpp:126
void process_message(const ::config &data, bool whisper=false)
Definition chatbox.cpp:575
lobby_chat_window * whisper_window_open(const std::string &name, bool open_new)
Check if a whisper window for user "name" is open, if open_new is true then it will be created if not...
Definition chatbox.cpp:385
void switch_to_window(lobby_chat_window *t)
Switch to the window given by a valid pointer (e.g.
Definition chatbox.cpp:130
void close_window_button_callback(const std::string &room_name, bool &handled, bool &halt)
Definition chatbox.cpp:455
std::size_t active_window_
Definition chatbox.hpp:132
virtual void add_whisper_sent(const std::string &receiver, const std::string &message) override
Inherited form chat_handler.
Definition chatbox.cpp:290
void process_network_data(const ::config &data)
Definition chatbox.cpp:625
void increment_waiting_whispers(const std::string &name)
Mark the whisper window for "name" as having one more pending message.
Definition chatbox.cpp:468
std::function< void(void)> active_window_changed_callback_
Definition chatbox.hpp:134
listbox * roomlistbox_
Definition chatbox.hpp:124
void increment_waiting_messages(const std::string &room)
Mark the room window for "room" as having one more pending message.
Definition chatbox.cpp:482
void signal_handler_receive_keyboard_focus(const event::ui_event event)
Definition chatbox.cpp:634
void send_to_server(const ::config &cfg) override
Definition chatbox.cpp:463
virtual void add_chat_room_message_received(const std::string &room, const std::string &speaker, const std::string &message) override
Inherited form chat_handler.
Definition chatbox.cpp:341
void load_log(std::map< std::string, chatroom_log > &log, bool show_lobby)
Definition chatbox.cpp:90
virtual void add_whisper_received(const std::string &sender, const std::string &message) override
Inherited form chat_handler.
Definition chatbox.cpp:302
virtual void add_chat_message(const std::chrono::system_clock::time_point &time, const std::string &speaker, int side, const std::string &message, events::chat_handler::MESSAGE_TYPE type=events::chat_handler::MESSAGE_PRIVATE) override
Inherited form chat_handler.
Definition chatbox.cpp:274
void finalize_setup()
Initializes the internal sub-widget pointers.
Definition chatbox.cpp:73
void chat_input_keypress_callback(const SDL_Keycode key)
Definition chatbox.cpp:149
void add_room_window_message(const std::string &room, const std::string &sender, const std::string &message)
Add a message to the window for room "room".
Definition chatbox.cpp:553
void active_window_changed()
Definition chatbox.cpp:115
std::vector< lobby_chat_window > open_windows_
Definition chatbox.hpp:130
bool whisper_window_active(const std::string &name)
Definition chatbox.cpp:367
A generic container base class.
Main class to show messages to the user.
Definition message.hpp:36
Base container class.
Definition grid.hpp:32
grid & add_row(const widget_item &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
Definition listbox.cpp:92
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
Definition listbox.cpp:256
bool select_row(const unsigned row, const bool select=true)
Selects a row.
Definition listbox.cpp:267
void remove_row(const unsigned row, unsigned count=1)
Removes a row in the listbox.
Definition listbox.cpp:108
int get_selected_row() const
Returns the first selected row.
Definition listbox.cpp:290
const grid & page_grid(const unsigned page) const
Returns the grid for the page.
void remove_page(const unsigned page, unsigned count=1)
Removes a page in the multi page.
grid & add_page(const widget_item &item)
Adds single page to the grid.
void select_page(const unsigned page, const bool select=true)
Selects a page.
std::string get_value()
virtual void set_label(const t_string &label) override
void set_value(const t_string &label)
@ END
Go to the end position.
Definition scrollbar.hpp:58
void scroll_vertical_scrollbar(const scrollbar_base::scroll_mode scroll)
Scrolls the vertical scrollbar.
unsigned get_vertical_scrollbar_item_position() const
Returns current position of the vertical scrollbar.
void set_vertical_scrollbar_item_position(const unsigned position)
Move the vertical scrollbar to a position.
virtual void set_use_markup(bool use_markup)
std::string get_value() const
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
bool is_composing() const
void save_to_history()
Saves the text in the widget to the history.
Definition text_box.hpp:132
Base class for all widgets.
Definition widget.hpp:55
T * find_widget(const std::string_view id, const bool must_be_active, const bool must_exist)
Gets a widget with the wanted id.
Definition widget.hpp:747
void set_visible(const visibility visible)
Definition widget.cpp:479
const std::string & id() const
Definition widget.cpp:110
window * get_window()
Get the parent window.
Definition widget.cpp:117
@ visible
The user sets the widget visible, that means:
@ hidden
The user sets the widget hidden, that means:
void keyboard_capture(widget *widget)
Definition window.cpp:1197
void notify_event(const std::string &name, const config &data)
Definition manager.cpp:144
static plugins_manager * get()
Definition manager.cpp:58
static prefs & get()
bool is_ignored(const std::string &nick)
bool is_friend(const std::string &nick)
std::string login()
bool auto_open_whisper_windows()
#define LOG_HEADER
const config * cfg
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
static std::string _(const char *str)
Definition gettext.hpp:100
#define DBG_GUI_G
Definition log.hpp:41
#define DBG_GUI_E
Definition log.hpp:35
This file contains the window object, this object is a top level container which has the event manage...
#define LOG_LB
#define ERR_LB
#define DBG_LB
Standard logging facilities (interface).
std::string escape_text(std::string_view text)
Escapes the pango markup characters in a text.
Definition escape.hpp:33
ui_event
The event sent to the dispatcher.
Definition handler.hpp:115
Generic file dialog.
std::map< std::string, widget_item > widget_data
Definition widget.hpp:36
std::map< std::string, t_string > widget_item
Definition widget.hpp:33
Functions to load and save images from/to disk.
Contains the implementation details for lexical_cast and shouldn't be used directly.
std::string italic(Args &&... data)
Applies italic Pango markup to the input.
Definition markup.hpp:176
std::string bold(Args &&... data)
Applies bold Pango markup to the input.
Definition markup.hpp:161
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition markup.hpp:110
lobby_info * get_lobby_info()
Returns the lobby_info object for the given session.
void send_to_server(const config &data)
Attempts to send given data to server if a connection is open.
notify_mode
std::string dsgettext(const char *domainname, const char *msgid)
Definition gettext.cpp:434
auto find(Container &container, const Value &value, const Projection &projection={})
Definition general.hpp:213
std::string join(const Range &v, const std::string &s=",")
Generates a new string joining container items in a list.
bool word_match(const std::string &message, const std::string &word)
Check if a message contains a word.
bool word_completion(std::string &text, std::vector< std::string > &wordlist)
Try to complete the last word of 'text' with the 'wordlist'.
std::string_view data
Definition picture.cpp:188
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
chatbox_definition(const config &cfg)
Definition chatbox.cpp:644
virtual std::unique_ptr< widget > build() const override
Definition chatbox.cpp:669
std::string definition
Parameters for the styled_widget.
std::vector< state_definition > state
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)