add mp chatbox widget
to be used in mp lobbay and mp connect.
This commit is contained in:
parent
e654fbbb49
commit
1c2bb78d15
9 changed files with 1225 additions and 871 deletions
|
@ -954,7 +954,9 @@
|
|||
grow_factor = 1
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
{_GUI_CHAT_AREA}
|
||||
[mp_chatbox]
|
||||
id = "chat"
|
||||
[/mp_chatbox]
|
||||
[/column]
|
||||
[column]
|
||||
grow_factor = 0
|
||||
|
@ -1041,7 +1043,9 @@
|
|||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
{GUI_FORCE_WIDGET_MINIMUM_SIZE 0 "((screen_height * 30 / 100))" (
|
||||
{_GUI_CHAT_AREA}
|
||||
[mp_chatbox]
|
||||
id = "chat"
|
||||
[/mp_chatbox]
|
||||
)}
|
||||
[/column]
|
||||
[/row]
|
||||
|
@ -1060,6 +1064,42 @@
|
|||
[/resolution]
|
||||
[/window]
|
||||
|
||||
[mp_chatbox_definition]
|
||||
id = "default"
|
||||
description = "Mp chatbox"
|
||||
|
||||
[resolution]
|
||||
|
||||
min_width = 0
|
||||
min_height = 0
|
||||
|
||||
default_width = 0
|
||||
default_height = 0
|
||||
|
||||
max_width = 0
|
||||
max_height = 0
|
||||
|
||||
[background]
|
||||
|
||||
[draw]
|
||||
|
||||
[/draw]
|
||||
|
||||
[/background]
|
||||
|
||||
[foreground]
|
||||
|
||||
[draw]
|
||||
|
||||
[/draw]
|
||||
|
||||
[/foreground]
|
||||
|
||||
{_GUI_CHAT_AREA}
|
||||
|
||||
[/resolution]
|
||||
|
||||
[/mp_chatbox_definition]
|
||||
#undef _GUI_CONTROL_AREA
|
||||
#undef _GUI_CHAT_AREA
|
||||
#undef _GUI_FILTER_AREA
|
||||
|
|
|
@ -534,6 +534,7 @@ set(wesnoth-gui_widget_SRC
|
|||
gui/widgets/matrix.cpp
|
||||
gui/widgets/menu_button.cpp
|
||||
gui/widgets/minimap.cpp
|
||||
gui/widgets/mp_chatbox.cpp
|
||||
gui/widgets/multi_page.cpp
|
||||
gui/widgets/pane.cpp
|
||||
gui/widgets/panel.cpp
|
||||
|
|
|
@ -447,6 +447,7 @@ wesnoth_sources = Split("""
|
|||
gui/widgets/matrix.cpp
|
||||
gui/widgets/menu_button.cpp
|
||||
gui/widgets/minimap.cpp
|
||||
gui/widgets/mp_chatbox.cpp
|
||||
gui/widgets/multi_page.cpp
|
||||
gui/widgets/pane.cpp
|
||||
gui/widgets/panel.cpp
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "map/exception.hpp"
|
||||
#include "wml_exception.hpp"
|
||||
#include "wesnothd_connection.hpp"
|
||||
#include "mp_ui_alerts.hpp"
|
||||
#include <iterator>
|
||||
|
||||
static lg::log_domain log_engine("engine");
|
||||
|
@ -65,7 +66,36 @@ void lobby_info::delete_games()
|
|||
delete v.second;
|
||||
}
|
||||
}
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
void do_mp_notify(t_notify_mode mode, const std::string & sender, const std::string & message)
|
||||
{
|
||||
switch (mode) {
|
||||
case NOTIFY_WHISPER:
|
||||
case NOTIFY_WHISPER_OTHER_WINDOW:
|
||||
case NOTIFY_OWN_NICK:
|
||||
mp_ui_alerts::private_message(true, sender, message);
|
||||
break;
|
||||
case NOTIFY_FRIEND_MESSAGE:
|
||||
mp_ui_alerts::friend_message(true, sender, message);
|
||||
break;
|
||||
case NOTIFY_SERVER_MESSAGE:
|
||||
mp_ui_alerts::server_message(true, sender, message);
|
||||
break;
|
||||
case NOTIFY_LOBBY_QUIT:
|
||||
mp_ui_alerts::player_leaves(true);
|
||||
break;
|
||||
case NOTIFY_LOBBY_JOIN:
|
||||
mp_ui_alerts::player_joins(true);
|
||||
break;
|
||||
case NOTIFY_MESSAGE:
|
||||
mp_ui_alerts::public_message(true, sender, message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace
|
||||
{
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ public:
|
|||
return users_;
|
||||
}
|
||||
const std::vector<user_info*>& users_sorted() const;
|
||||
twesnothd_connection& wesnothd_connection() const { return wesnothd_connection_; }
|
||||
|
||||
private:
|
||||
void process_userlist();
|
||||
|
@ -119,4 +120,23 @@ private:
|
|||
twesnothd_connection& wesnothd_connection_;
|
||||
};
|
||||
|
||||
enum t_notify_mode {
|
||||
NOTIFY_NONE,
|
||||
NOTIFY_MESSAGE,
|
||||
NOTIFY_MESSAGE_OTHER_WINDOW,
|
||||
NOTIFY_SERVER_MESSAGE,
|
||||
NOTIFY_OWN_NICK,
|
||||
NOTIFY_FRIEND_MESSAGE,
|
||||
NOTIFY_WHISPER,
|
||||
NOTIFY_WHISPER_OTHER_WINDOW,
|
||||
NOTIFY_LOBBY_JOIN,
|
||||
NOTIFY_LOBBY_QUIT,
|
||||
NOTIFY_COUNT
|
||||
};
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
void do_mp_notify(t_notify_mode mode, const std::string & sender, const std::string & message);
|
||||
inline void do_mp_notify(t_notify_mode mode) { do_mp_notify(mode, "", ""); }
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#endif
|
||||
#include "gui/widgets/menu_button.hpp"
|
||||
#include "gui/widgets/minimap.hpp"
|
||||
#include "gui/widgets/mp_chatbox.hpp"
|
||||
#include "gui/widgets/multi_page.hpp"
|
||||
#include "gui/widgets/scroll_label.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
|
@ -49,7 +50,6 @@
|
|||
#include "gettext.hpp"
|
||||
#include "lobby_preferences.hpp"
|
||||
#include "log.hpp"
|
||||
#include "mp_ui_alerts.hpp"
|
||||
#include "playmp_controller.hpp"
|
||||
#include "wesnothd_connection.hpp"
|
||||
|
||||
|
@ -132,179 +132,6 @@ void tplayer_list::update_sort_icons()
|
|||
sort_by_relation->set_icon_name(sort_by_relation->get_value() ? "lobby/sort-friend.png" : "lobby/sort-friend-off.png");
|
||||
}
|
||||
|
||||
void tlobby_main::send_chat_message(const std::string& message,
|
||||
bool /*allies_only*/)
|
||||
{
|
||||
config data, msg;
|
||||
msg["message"] = message;
|
||||
msg["sender"] = preferences::login();
|
||||
data.add_child("message", msg);
|
||||
|
||||
add_chat_message(time(nullptr), preferences::login(), 0, message); // local
|
||||
// echo
|
||||
wesnothd_connection_.send_data(data);
|
||||
}
|
||||
|
||||
void tlobby_main::user_relation_changed(const std::string& /*name*/)
|
||||
{
|
||||
player_list_dirty_ = true;
|
||||
}
|
||||
|
||||
void tlobby_main::add_chat_message(const time_t& /*time*/,
|
||||
const std::string& speaker,
|
||||
int /*side*/,
|
||||
const std::string& message,
|
||||
events::chat_handler::MESSAGE_TYPE /*type*/)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>" << speaker << ":</b> ";
|
||||
ss << font::escape_text(message);
|
||||
append_to_chatbox(ss.str());
|
||||
}
|
||||
|
||||
|
||||
void tlobby_main::add_whisper_sent(const std::string& receiver,
|
||||
const std::string& message)
|
||||
{
|
||||
if(whisper_window_active(receiver)) {
|
||||
add_active_window_message(preferences::login(), message, true);
|
||||
} else if(tlobby_chat_window* t = whisper_window_open(
|
||||
receiver, preferences::auto_open_whisper_windows())) {
|
||||
switch_to_window(t);
|
||||
add_active_window_message(preferences::login(), message, true);
|
||||
} else {
|
||||
utils::string_map symbols;
|
||||
symbols["receiver"] = receiver;
|
||||
add_active_window_whisper(VGETTEXT("whisper to $receiver", symbols),
|
||||
message, true);
|
||||
}
|
||||
lobby_info_.get_whisper_log(receiver)
|
||||
.add_message(preferences::login(), message);
|
||||
}
|
||||
|
||||
void tlobby_main::add_whisper_received(const std::string& sender,
|
||||
const std::string& message)
|
||||
{
|
||||
bool can_go_to_active = !preferences::whisper_friends_only()
|
||||
|| preferences::is_friend(sender);
|
||||
bool can_open_new = preferences::auto_open_whisper_windows()
|
||||
&& can_go_to_active;
|
||||
lobby_info_.get_whisper_log(sender).add_message(sender, message);
|
||||
if(whisper_window_open(sender, can_open_new)) {
|
||||
if(whisper_window_active(sender)) {
|
||||
add_active_window_message(sender, message);
|
||||
do_notify(NOTIFY_WHISPER, sender, message);
|
||||
} else {
|
||||
add_whisper_window_whisper(sender, message);
|
||||
increment_waiting_whsipers(sender);
|
||||
do_notify(NOTIFY_WHISPER_OTHER_WINDOW, sender, message);
|
||||
}
|
||||
} else if(can_go_to_active) {
|
||||
add_active_window_whisper(sender, message);
|
||||
do_notify(NOTIFY_WHISPER, sender, message);
|
||||
} else {
|
||||
LOG_LB << "Ignoring whisper from " << sender << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::add_chat_room_message_sent(const std::string& room,
|
||||
const std::string& message)
|
||||
{
|
||||
// do not open room window here, player should be in the room before sending
|
||||
// messages yo it should be allowed to happen
|
||||
if(tlobby_chat_window* t = room_window_open(room, false)) {
|
||||
room_info* ri = lobby_info_.get_room(room);
|
||||
assert(ri);
|
||||
if(!room_window_active(room)) {
|
||||
switch_to_window(t);
|
||||
}
|
||||
ri->log().add_message(preferences::login(), message);
|
||||
add_active_window_message(preferences::login(), message, true);
|
||||
} else {
|
||||
LOG_LB << "Cannot add sent message to ui for room " << room
|
||||
<< ", player not in the room\n";
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::add_chat_room_message_received(const std::string& room,
|
||||
const std::string& speaker,
|
||||
const std::string& message)
|
||||
{
|
||||
if(room_info* ri = lobby_info_.get_room(room)) {
|
||||
t_notify_mode notify_mode = NOTIFY_NONE;
|
||||
ri->log().add_message(speaker, message);
|
||||
if(room_window_active(room)) {
|
||||
add_active_window_message(speaker, message);
|
||||
notify_mode = NOTIFY_MESSAGE;
|
||||
} else {
|
||||
add_room_window_message(room, speaker, message);
|
||||
increment_waiting_messages(room);
|
||||
notify_mode = NOTIFY_MESSAGE_OTHER_WINDOW;
|
||||
}
|
||||
if(speaker == "server") {
|
||||
notify_mode = NOTIFY_SERVER_MESSAGE;
|
||||
} else if(utils::word_match(message, preferences::login())) {
|
||||
notify_mode = NOTIFY_OWN_NICK;
|
||||
} else if(preferences::is_friend(speaker)) {
|
||||
notify_mode = NOTIFY_FRIEND_MESSAGE;
|
||||
}
|
||||
do_notify(notify_mode, speaker, message);
|
||||
} else {
|
||||
LOG_LB << "Discarding message to room " << room << " from " << speaker
|
||||
<< " (room not open)\n";
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::append_to_chatbox(const std::string& text, const bool force_scroll)
|
||||
{
|
||||
append_to_chatbox(text, active_window_, force_scroll);
|
||||
}
|
||||
|
||||
void tlobby_main::append_to_chatbox(const std::string& text, size_t id, const bool force_scroll)
|
||||
{
|
||||
tgrid& grid = chat_log_container_->page_grid(id);
|
||||
tscroll_label& log = find_widget<tscroll_label>(&grid, "log_text", false);
|
||||
const bool chatbox_at_end = log.vertical_scrollbar_at_end();
|
||||
const unsigned chatbox_position = log.get_vertical_scrollbar_item_position();
|
||||
log.set_use_markup(true);
|
||||
log.set_label(log.label() + "\n" +
|
||||
"<span color='#bcb088'>" + preferences::get_chat_timestamp(time(0)) + text + "</span>");
|
||||
|
||||
if(chatbox_at_end || force_scroll) {
|
||||
log.scroll_vertical_scrollbar(tscrollbar_::END);
|
||||
} else {
|
||||
log.set_vertical_scrollbar_item_position(chatbox_position);
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::do_notify(t_notify_mode mode, const std::string & sender, const std::string & message)
|
||||
{
|
||||
switch(mode) {
|
||||
case NOTIFY_WHISPER:
|
||||
case NOTIFY_WHISPER_OTHER_WINDOW:
|
||||
case NOTIFY_OWN_NICK:
|
||||
mp_ui_alerts::private_message(true, sender, message);
|
||||
break;
|
||||
case NOTIFY_FRIEND_MESSAGE:
|
||||
mp_ui_alerts::friend_message(true, sender, message);
|
||||
break;
|
||||
case NOTIFY_SERVER_MESSAGE:
|
||||
mp_ui_alerts::server_message(true, sender, message);
|
||||
break;
|
||||
case NOTIFY_LOBBY_QUIT:
|
||||
mp_ui_alerts::player_leaves(true);
|
||||
break;
|
||||
case NOTIFY_LOBBY_JOIN:
|
||||
mp_ui_alerts::player_joins(true);
|
||||
break;
|
||||
case NOTIFY_MESSAGE:
|
||||
mp_ui_alerts::public_message(true, sender, message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool tlobby_main::logout_prompt()
|
||||
{
|
||||
return show_prompt(_("Do you really want to log out?"));
|
||||
|
@ -317,13 +144,9 @@ tlobby_main::tlobby_main(const config& game_config,
|
|||
, legacy_result_(QUIT)
|
||||
, game_config_(game_config)
|
||||
, gamelistbox_(nullptr)
|
||||
, roomlistbox_(nullptr)
|
||||
, chat_log_container_(nullptr)
|
||||
, chat_input_(nullptr)
|
||||
, window_(nullptr)
|
||||
, lobby_info_(info)
|
||||
, preferences_callback_()
|
||||
, open_windows_()
|
||||
, active_window_(0)
|
||||
, filter_friends_(nullptr)
|
||||
, filter_ignored_(nullptr)
|
||||
|
@ -729,12 +552,12 @@ void tlobby_main::update_playerlist()
|
|||
return;
|
||||
SCOPE_LB;
|
||||
DBG_LB << "Playerlist update: " << lobby_info_.users().size() << "\n";
|
||||
lobby_info_.update_user_statuses(selected_game_id_, active_window_room());
|
||||
lobby_info_.update_user_statuses(selected_game_id_, chatbox_->active_window_room());
|
||||
lobby_info_.sort_users(player_list_.sort_by_name->get_value_bool(),
|
||||
player_list_.sort_by_relation->get_value_bool());
|
||||
|
||||
bool lobby = false;
|
||||
if(room_info* ri = active_window_room()) {
|
||||
if(room_info* ri = chatbox_->active_window_room()) {
|
||||
if(ri->name() == "lobby") {
|
||||
lobby = true;
|
||||
}
|
||||
|
@ -880,17 +703,6 @@ void tlobby_main::signal_handler_key_down(SDLKey key, bool& handled, bool& halt)
|
|||
void tlobby_main::pre_show(twindow& window)
|
||||
{
|
||||
SCOPE_LB;
|
||||
roomlistbox_ = find_widget<tlistbox>(&window, "room_list", false, true);
|
||||
#ifdef GUI2_EXPERIMENTAL_LISTBOX
|
||||
connect_signal_notify_modified(
|
||||
*roomlistbox_,
|
||||
std::bind(&tlobby_main::room_switch_callback,
|
||||
*this,
|
||||
std::ref(window)));
|
||||
#else
|
||||
roomlistbox_->set_callback_value_change(
|
||||
dialog_callback<tlobby_main, &tlobby_main::room_switch_callback>);
|
||||
#endif
|
||||
|
||||
gamelistbox_ = find_widget<tlistbox>(&window, "game_list", false, true);
|
||||
#ifdef GUI2_EXPERIMENTAL_LISTBOX
|
||||
|
@ -918,8 +730,6 @@ void tlobby_main::pre_show(twindow& window)
|
|||
player_list_.sort_by_relation->set_callback_state_change(
|
||||
std::bind(&tlobby_main::player_filter_callback, this, _1));
|
||||
|
||||
chat_log_container_ = find_widget<tmulti_page>(&window, "chat_log_container", false, true);
|
||||
|
||||
window.set_enter_disabled(true);
|
||||
window.set_escape_disabled(true);
|
||||
// A new key handler to deal with escape in a different manner.
|
||||
|
@ -929,16 +739,9 @@ void tlobby_main::pre_show(twindow& window)
|
|||
|
||||
window_ = &window;
|
||||
|
||||
chat_input_ = find_widget<ttext_box>(&window, "chat_input", false, true);
|
||||
assert(chat_input_);
|
||||
connect_signal_pre_key_press(
|
||||
*chat_input_,
|
||||
std::bind(&tlobby_main::chat_input_keypress_callback,
|
||||
this,
|
||||
_3,
|
||||
_4,
|
||||
_5,
|
||||
std::ref(window)));
|
||||
chatbox_ = find_widget<tmp_chatbox>(&window, "chat", false, true);
|
||||
chatbox_->set_lobby_info(lobby_info_);
|
||||
chatbox_->set_active_window_changed_callback([this]() { player_list_dirty_ = true; });
|
||||
|
||||
connect_signal_mouse_left_click(
|
||||
find_widget<tbutton>(&window, "create", false),
|
||||
|
@ -1004,8 +807,8 @@ void tlobby_main::pre_show(twindow& window)
|
|||
*filter_text_,
|
||||
std::bind(&tlobby_main::game_filter_keypress_callback, this, _5));
|
||||
|
||||
room_window_open("lobby", true);
|
||||
active_window_changed();
|
||||
chatbox_->room_window_open("lobby", true);
|
||||
chatbox_->active_window_changed();
|
||||
game_filter_reload();
|
||||
|
||||
// Force first update to be directly.
|
||||
|
@ -1042,7 +845,7 @@ void tlobby_main::pre_show(twindow& window)
|
|||
plugins_context_->set_callback("create", [this, &window](const config&) { create_button_callback(window); }, true);
|
||||
plugins_context_->set_callback("quit", [&window](const config&) { window.set_retval(twindow::CANCEL); }, false);
|
||||
|
||||
plugins_context_->set_callback("chat", [this](const config& cfg) { send_chat_message(cfg["message"], false); }, true);
|
||||
plugins_context_->set_callback("chat", [this](const config& cfg) { chatbox_->send_chat_message(cfg["message"], false); }, true);
|
||||
plugins_context_->set_callback("select_game", [this](const config& cfg) {
|
||||
selected_game_id_ = cfg.has_attribute("id") ? cfg["id"].to_int() : lobby_info_.games()[cfg["index"].to_int()]->id;
|
||||
}, true);
|
||||
|
@ -1059,242 +862,6 @@ void tlobby_main::post_show(twindow& /*window*/)
|
|||
plugins_context_.reset();
|
||||
}
|
||||
|
||||
room_info* tlobby_main::active_window_room()
|
||||
{
|
||||
const tlobby_chat_window& t = open_windows_[active_window_];
|
||||
if(t.whisper)
|
||||
return nullptr;
|
||||
return lobby_info_.get_room(t.name);
|
||||
}
|
||||
|
||||
tlobby_chat_window* tlobby_main::room_window_open(const std::string& room,
|
||||
bool open_new)
|
||||
{
|
||||
return search_create_window(room, false, open_new);
|
||||
}
|
||||
|
||||
tlobby_chat_window* tlobby_main::whisper_window_open(const std::string& name,
|
||||
bool open_new)
|
||||
{
|
||||
return search_create_window(name, true, open_new);
|
||||
}
|
||||
|
||||
tlobby_chat_window* tlobby_main::search_create_window(const std::string& name,
|
||||
bool whisper,
|
||||
bool open_new)
|
||||
{
|
||||
for(auto & t : open_windows_) {
|
||||
if(t.name == name && t.whisper == whisper)
|
||||
return &t;
|
||||
}
|
||||
|
||||
if(open_new) {
|
||||
open_windows_.push_back(tlobby_chat_window(name, whisper));
|
||||
std::map<std::string, string_map> data;
|
||||
utils::string_map symbols;
|
||||
symbols["name"] = name;
|
||||
if(whisper) {
|
||||
add_label_data(data, "log_text",
|
||||
VGETTEXT("Whisper session with $name started. "
|
||||
"If you do not want to receive messages "
|
||||
"from this user, "
|
||||
"type /ignore $name\n",
|
||||
symbols));
|
||||
} else {
|
||||
add_label_data(data, "log_text", VGETTEXT("<i>Room $name joined</i>", symbols));
|
||||
lobby_info_.open_room(name);
|
||||
}
|
||||
|
||||
chat_log_container_->add_page(data);
|
||||
std::map<std::string, string_map> data2;
|
||||
add_label_data(data2, "room", whisper ? font::escape_text("<" + name + ">") : name);
|
||||
tgrid* row_grid = &roomlistbox_->add_row(data2);
|
||||
|
||||
tbutton& close_button = find_widget<tbutton>(row_grid, "close_window", false);
|
||||
connect_signal_mouse_left_click(close_button,
|
||||
std::bind(&tlobby_main::close_window_button_callback, this, open_windows_.back(),
|
||||
std::placeholders::_3, std::placeholders::_4));
|
||||
|
||||
if(name == "lobby") {
|
||||
close_button.set_visible(tcontrol::tvisible::hidden);
|
||||
}
|
||||
|
||||
return &open_windows_.back();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool tlobby_main::whisper_window_active(const std::string& name)
|
||||
{
|
||||
const tlobby_chat_window& t = open_windows_[active_window_];
|
||||
return t.name == name && t.whisper == true;
|
||||
}
|
||||
|
||||
bool tlobby_main::room_window_active(const std::string& room)
|
||||
{
|
||||
const tlobby_chat_window& t = open_windows_[active_window_];
|
||||
return t.name == room && t.whisper == false;
|
||||
}
|
||||
|
||||
void tlobby_main::increment_waiting_whsipers(const std::string& name)
|
||||
{
|
||||
if(tlobby_chat_window* t = whisper_window_open(name, false)) {
|
||||
t->pending_messages++;
|
||||
if(t->pending_messages == 1) {
|
||||
DBG_LB << "do whisper pending mark row " << (t - &open_windows_[0])
|
||||
<< " with " << t->name << "\n";
|
||||
tgrid* grid = roomlistbox_->get_row_grid(t - &open_windows_[0]);
|
||||
// this breaks for some reason
|
||||
// tlabel& label = grid->get_widget<tlabel>("room", false);
|
||||
// label.set_use_markup(true);
|
||||
// label.set_label(colorize("<" + t->name + ">", "red"));
|
||||
find_widget<timage>(grid, "pending_messages", false)
|
||||
.set_visible(twidget::tvisible::visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::increment_waiting_messages(const std::string& room)
|
||||
{
|
||||
if(tlobby_chat_window* t = room_window_open(room, false)) {
|
||||
t->pending_messages++;
|
||||
if(t->pending_messages == 1) {
|
||||
int idx = t - &open_windows_[0];
|
||||
DBG_LB << "do room pending mark row " << idx << " with " << t->name
|
||||
<< "\n";
|
||||
tgrid* grid = roomlistbox_->get_row_grid(idx);
|
||||
// this breaks for some reason
|
||||
// tlabel& label = grid->get_widget<tlabel>("room", false);
|
||||
// label.set_use_markup(true);
|
||||
// label.set_label(colorize(t->name, "red"));
|
||||
find_widget<timage>(grid, "pending_messages", false)
|
||||
.set_visible(twidget::tvisible::visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::add_whisper_window_whisper(const std::string& sender,
|
||||
const std::string& message)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>" << sender << ":</b> " << font::escape_text(message);
|
||||
tlobby_chat_window* t = whisper_window_open(sender, false);
|
||||
if(!t) {
|
||||
ERR_LB << "Whisper window not open in add_whisper_window_whisper for "
|
||||
<< sender << "\n";
|
||||
return;
|
||||
}
|
||||
append_to_chatbox(ss.str(), t - &open_windows_[0], false);
|
||||
}
|
||||
|
||||
void tlobby_main::add_active_window_whisper(const std::string& sender,
|
||||
const std::string& message,
|
||||
const bool force_scroll)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>"
|
||||
<< "whisper: " << sender << ":</b> " << font::escape_text(message);
|
||||
append_to_chatbox(ss.str(), force_scroll);
|
||||
}
|
||||
|
||||
void tlobby_main::add_room_window_message(const std::string& room,
|
||||
const std::string& sender,
|
||||
const std::string& message)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>" << sender << ":</b> " << font::escape_text(message);
|
||||
tlobby_chat_window* t = room_window_open(room, false);
|
||||
if(!t) {
|
||||
ERR_LB << "Room window not open in add_room_window_message for " << room
|
||||
<< "\n";
|
||||
return;
|
||||
}
|
||||
append_to_chatbox(ss.str(), t - &open_windows_[0], false);
|
||||
}
|
||||
|
||||
void tlobby_main::add_active_window_message(const std::string& sender,
|
||||
const std::string& message,
|
||||
const bool force_scroll)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>" << sender << ":</b> " << font::escape_text(message);
|
||||
append_to_chatbox(ss.str(), force_scroll);
|
||||
}
|
||||
|
||||
void tlobby_main::switch_to_window(tlobby_chat_window* t)
|
||||
{
|
||||
switch_to_window(t - &open_windows_[0]);
|
||||
}
|
||||
|
||||
void tlobby_main::switch_to_window(size_t id)
|
||||
{
|
||||
active_window_ = id;
|
||||
assert(active_window_ < open_windows_.size());
|
||||
chat_log_container_->select_page(active_window_);
|
||||
roomlistbox_->select_row(active_window_);
|
||||
active_window_changed();
|
||||
}
|
||||
|
||||
void tlobby_main::active_window_changed()
|
||||
{
|
||||
tlobby_chat_window& t = open_windows_[active_window_];
|
||||
|
||||
DBG_LB << "active window changed to " << active_window_ << " "
|
||||
<< (t.whisper ? "w" : "r") << " " << t.name << "\n";
|
||||
|
||||
// clear pending messages notification in room listbox
|
||||
tgrid* grid = roomlistbox_->get_row_grid(active_window_);
|
||||
find_widget<timage>(grid, "pending_messages", false).set_visible(twidget::tvisible::hidden);
|
||||
t.pending_messages = 0;
|
||||
|
||||
player_list_dirty_ = true;
|
||||
}
|
||||
|
||||
|
||||
void tlobby_main::close_active_window()
|
||||
{
|
||||
DBG_LB << "Close window button clicked\n";
|
||||
return close_window(active_window_);
|
||||
}
|
||||
|
||||
void tlobby_main::close_window(size_t idx)
|
||||
{
|
||||
const tlobby_chat_window& t = open_windows_[idx];
|
||||
bool active_changed = idx == active_window_;
|
||||
DBG_LB << "Close window " << idx << " - " << t.name << "\n";
|
||||
|
||||
if((t.name == "lobby" && t.whisper == false) || open_windows_.size() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(t.whisper == false) {
|
||||
// closing a room window -- send a part to the server
|
||||
config data, msg;
|
||||
msg["room"] = t.name;
|
||||
msg["player"] = preferences::login();
|
||||
data.add_child("room_part", msg);
|
||||
wesnothd_connection_.send_data(data);
|
||||
}
|
||||
|
||||
if(active_window_ == open_windows_.size() - 1) {
|
||||
active_window_--;
|
||||
}
|
||||
|
||||
if(t.whisper) {
|
||||
lobby_info_.get_whisper_log(t.name).clear();
|
||||
} else {
|
||||
lobby_info_.close_room(t.name);
|
||||
}
|
||||
|
||||
open_windows_.erase(open_windows_.begin() + idx);
|
||||
roomlistbox_->remove_row(idx);
|
||||
roomlistbox_->select_row(active_window_);
|
||||
chat_log_container_->remove_page(idx);
|
||||
chat_log_container_->select_page(active_window_);
|
||||
if(active_changed)
|
||||
active_window_changed();
|
||||
}
|
||||
|
||||
void tlobby_main::network_handler()
|
||||
{
|
||||
if(gamelist_dirty_ && !delay_gamelist_update_
|
||||
|
@ -1327,44 +894,14 @@ void tlobby_main::network_handler()
|
|||
|
||||
void tlobby_main::process_network_data(const config& data)
|
||||
{
|
||||
if(const config& c = data.child("error")) {
|
||||
if (const config& c = data.child("error")) {
|
||||
throw wesnothd_error(c["message"]);
|
||||
} else if(const config& c = data.child("message")) {
|
||||
process_message(c);
|
||||
} else if(const config& c = data.child("whisper")) {
|
||||
process_message(c, true);
|
||||
} else if (chatbox_->process_network_data(data)) {
|
||||
|
||||
} else if(data.child("gamelist")) {
|
||||
process_gamelist(data);
|
||||
} else if(const config& c = data.child("gamelist_diff")) {
|
||||
process_gamelist_diff(c);
|
||||
} else if(const config& c = data.child("room_join")) {
|
||||
process_room_join(c);
|
||||
} else if(const config& c = data.child("room_part")) {
|
||||
process_room_part(c);
|
||||
} else if(const config& c = data.child("room_query_response")) {
|
||||
process_room_query_response(c);
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::process_message(const config& data, bool whisper /*= false*/)
|
||||
{
|
||||
std::string sender = data["sender"];
|
||||
DBG_LB << "process message from " << sender << " " << (whisper ? "(w)" : "")
|
||||
<< ", len " << data["message"].str().size() << '\n';
|
||||
if(preferences::is_ignored(sender))
|
||||
return;
|
||||
const std::string& message = data["message"];
|
||||
preferences::parse_admin_authentication(sender, message);
|
||||
if(whisper) {
|
||||
add_whisper_received(sender, message);
|
||||
} else {
|
||||
std::string room = data["room"];
|
||||
if(room.empty()) {
|
||||
LOG_LB << "Message without a room from " << sender
|
||||
<< ", assuming lobby\n";
|
||||
room = "lobby";
|
||||
}
|
||||
add_chat_room_message_received(room, sender, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1395,116 +932,6 @@ void tlobby_main::process_gamelist_diff(const config& data)
|
|||
}
|
||||
}
|
||||
|
||||
void tlobby_main::process_room_join(const config& data)
|
||||
{
|
||||
const std::string& room = data["room"];
|
||||
const std::string& player = data["player"];
|
||||
room_info* r = lobby_info_.get_room(room);
|
||||
DBG_LB << "room join: " << room << " " << player << " "
|
||||
<< static_cast<void*>(r) << "\n";
|
||||
|
||||
if(r) {
|
||||
if(player == preferences::login()) {
|
||||
if(const config& members = data.child("members")) {
|
||||
r->process_room_members(members);
|
||||
}
|
||||
} else {
|
||||
r->add_member(player);
|
||||
/* TODO: add/use preference */
|
||||
utils::string_map symbols;
|
||||
symbols["player"] = player;
|
||||
add_room_window_message(
|
||||
room,
|
||||
"server",
|
||||
VGETTEXT("$player has entered the room", symbols));
|
||||
}
|
||||
if(r == active_window_room()) {
|
||||
player_list_dirty_ = true;
|
||||
}
|
||||
} else {
|
||||
if(player == preferences::login()) {
|
||||
tlobby_chat_window* t = room_window_open(room, true);
|
||||
lobby_info_.open_room(room);
|
||||
r = lobby_info_.get_room(room);
|
||||
assert(r);
|
||||
if(const config& members = data.child("members")) {
|
||||
r->process_room_members(members);
|
||||
}
|
||||
switch_to_window(t);
|
||||
|
||||
const std::string& topic = data["topic"];
|
||||
if(!topic.empty()) {
|
||||
add_chat_room_message_received(
|
||||
"room", "server", room + ": " + topic);
|
||||
}
|
||||
} else {
|
||||
LOG_LB << "Discarding join info for a room the player is not in\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::process_room_part(const config& data)
|
||||
{
|
||||
// todo close room window when the part message is sent
|
||||
const std::string& room = data["room"];
|
||||
const std::string& player = data["player"];
|
||||
DBG_LB << "Room part: " << room << " " << player << "\n";
|
||||
room_info* r = lobby_info_.get_room(room);
|
||||
if(r) {
|
||||
r->remove_member(player);
|
||||
/* TODO: add/use preference */
|
||||
utils::string_map symbols;
|
||||
symbols["player"] = player;
|
||||
add_room_window_message(
|
||||
room, "server", VGETTEXT("$player has left the room", symbols));
|
||||
if(active_window_room() == r) {
|
||||
player_list_dirty_ = true;
|
||||
}
|
||||
} else {
|
||||
LOG_LB << "Discarding part info for a room the player is not in\n";
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::process_room_query_response(const config& data)
|
||||
{
|
||||
const std::string& room = data["room"];
|
||||
const std::string& message = data["message"];
|
||||
DBG_LB << "room query response: " << room << " " << message << "\n";
|
||||
if(room.empty()) {
|
||||
if(!message.empty()) {
|
||||
add_active_window_message("server", message);
|
||||
}
|
||||
if(const config& rooms = data.child("rooms")) {
|
||||
// TODO: this should really open a nice join room dialog instead
|
||||
std::stringstream ss;
|
||||
ss << "Rooms:";
|
||||
for(const auto & r : rooms.child_range("room"))
|
||||
{
|
||||
ss << " " << r["name"];
|
||||
}
|
||||
add_active_window_message("server", ss.str());
|
||||
}
|
||||
} else {
|
||||
if(room_window_open(room, false)) {
|
||||
if(!message.empty()) {
|
||||
add_chat_room_message_received(room, "server", message);
|
||||
}
|
||||
if(const config& members = data.child("members")) {
|
||||
room_info* r = lobby_info_.get_room(room);
|
||||
assert(r);
|
||||
r->process_room_members(members);
|
||||
if(r == active_window_room()) {
|
||||
player_list_dirty_ = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!message.empty()) {
|
||||
add_active_window_message("server", room + ": " + message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::observe_global_button_callback(twindow& window)
|
||||
{
|
||||
if(do_game_join(gamelistbox_->get_selected_row(), true)) {
|
||||
|
@ -1636,48 +1063,6 @@ bool tlobby_main::do_game_join(int idx, bool observe)
|
|||
return true;
|
||||
}
|
||||
|
||||
void tlobby_main::send_message_button_callback(twindow& /*window*/)
|
||||
{
|
||||
const std::string& input = chat_input_->get_value();
|
||||
if(input.empty())
|
||||
return;
|
||||
if(input[0] == '/') {
|
||||
// TODO: refactor do_speak so it uses context information about
|
||||
// opened window, so e.g. /ignore in a whisper session ignores
|
||||
// the other party without having to specify it's nick.
|
||||
chat_handler::do_speak(input);
|
||||
} else {
|
||||
config msg;
|
||||
send_message_to_active_window(input);
|
||||
}
|
||||
chat_input_->save_to_history();
|
||||
chat_input_->set_value("");
|
||||
}
|
||||
|
||||
void tlobby_main::send_message_to_active_window(const std::string& input)
|
||||
{
|
||||
tlobby_chat_window& t = open_windows_[active_window_];
|
||||
if(t.whisper) {
|
||||
send_whisper(t.name, input);
|
||||
add_whisper_sent(t.name, input);
|
||||
} else {
|
||||
send_chat_room_message(t.name, input);
|
||||
add_chat_room_message_sent(t.name, input);
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::close_window_button_callback(tlobby_chat_window& chat_window, bool& handled, bool& halt)
|
||||
{
|
||||
const int index = std::find_if(open_windows_.begin(), open_windows_.end(), [&chat_window](const tlobby_chat_window& room) {
|
||||
return room.name == chat_window.name;
|
||||
}) - open_windows_.begin();
|
||||
|
||||
close_window(index);
|
||||
|
||||
handled = true;
|
||||
halt = true;
|
||||
}
|
||||
|
||||
void tlobby_main::create_button_callback(twindow& window)
|
||||
{
|
||||
legacy_result_ = CREATE;
|
||||
|
@ -1705,49 +1090,6 @@ void tlobby_main::show_preferences_button_callback(twindow& window)
|
|||
}
|
||||
}
|
||||
|
||||
void tlobby_main::room_switch_callback(twindow& /*window*/)
|
||||
{
|
||||
switch_to_window(roomlistbox_->get_selected_row());
|
||||
}
|
||||
|
||||
void tlobby_main::chat_input_keypress_callback(bool& handled,
|
||||
bool& halt,
|
||||
const SDLKey key,
|
||||
twindow& window)
|
||||
{
|
||||
if(key == SDLK_RETURN || key == SDLK_KP_ENTER) {
|
||||
send_message_button_callback(window);
|
||||
handled = true;
|
||||
halt = true;
|
||||
} else if(key == SDLK_TAB) {
|
||||
std::string text = chat_input_->get_value();
|
||||
const std::vector<user_info>& match_infos = lobby_info_.users();
|
||||
std::vector<std::string> matches;
|
||||
|
||||
for(const auto & ui : match_infos)
|
||||
{
|
||||
if(ui.name != preferences::login()) {
|
||||
matches.push_back(ui.name);
|
||||
}
|
||||
}
|
||||
const bool line_start = utils::word_completion(text, matches);
|
||||
|
||||
if(matches.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(matches.size() == 1) {
|
||||
text.append(line_start ? ": " : " ");
|
||||
} else {
|
||||
std::string completion_list = utils::join(matches, " ");
|
||||
append_to_chatbox(completion_list);
|
||||
}
|
||||
chat_input_->set_value(text);
|
||||
handled = true;
|
||||
halt = true;
|
||||
}
|
||||
}
|
||||
|
||||
void tlobby_main::game_filter_reload()
|
||||
{
|
||||
lobby_info_.clear_game_filter();
|
||||
|
@ -1812,7 +1154,7 @@ void tlobby_main::player_filter_callback(gui2::twidget& /*widget*/)
|
|||
|
||||
void tlobby_main::user_dialog_callback(user_info* info)
|
||||
{
|
||||
tlobby_player_info dlg(*this, *info, lobby_info_);
|
||||
tlobby_player_info dlg(*chatbox_, *info, lobby_info_);
|
||||
|
||||
lobby_delay_gamelist_update_guard g(*this);
|
||||
|
||||
|
@ -1821,8 +1163,8 @@ void tlobby_main::user_dialog_callback(user_info* info)
|
|||
delay_playerlist_update_ = true;
|
||||
|
||||
if(dlg.result_open_whisper()) {
|
||||
tlobby_chat_window* t = whisper_window_open(info->name, true);
|
||||
switch_to_window(t);
|
||||
tlobby_chat_window* t = chatbox_->whisper_window_open(info->name, true);
|
||||
chatbox_->switch_to_window(t);
|
||||
}
|
||||
|
||||
selected_game_id_ = info->game_id;
|
||||
|
|
|
@ -41,17 +41,7 @@ class ttext_box;
|
|||
class twindow;
|
||||
class tmulti_page;
|
||||
class ttoggle_button;
|
||||
|
||||
struct tlobby_chat_window
|
||||
{
|
||||
tlobby_chat_window(const std::string& name, bool whisper)
|
||||
: name(name), whisper(whisper), pending_messages(0)
|
||||
{
|
||||
}
|
||||
std::string name;
|
||||
bool whisper;
|
||||
int pending_messages;
|
||||
};
|
||||
class tmp_chatbox;
|
||||
|
||||
struct tsub_player_list
|
||||
{
|
||||
|
@ -77,7 +67,7 @@ struct tplayer_list
|
|||
ttree_view* tree;
|
||||
};
|
||||
|
||||
class tlobby_main : public tdialog, public quit_confirmation, private events::chat_handler, private plugin_executor
|
||||
class tlobby_main : public tdialog, public quit_confirmation, private plugin_executor
|
||||
{
|
||||
public:
|
||||
tlobby_main(const config& game_config, lobby_info& info, twesnothd_connection &wesnothd_connection);
|
||||
|
@ -91,7 +81,7 @@ public:
|
|||
|
||||
void update_gamelist();
|
||||
|
||||
void send_to_server(const config& cfg) override;
|
||||
void send_to_server(const config& cfg);
|
||||
|
||||
protected:
|
||||
void update_gamelist_header();
|
||||
|
@ -120,165 +110,19 @@ public:
|
|||
return legacy_result_;
|
||||
}
|
||||
|
||||
enum t_notify_mode {
|
||||
NOTIFY_NONE,
|
||||
NOTIFY_MESSAGE,
|
||||
NOTIFY_MESSAGE_OTHER_WINDOW,
|
||||
NOTIFY_SERVER_MESSAGE,
|
||||
NOTIFY_OWN_NICK,
|
||||
NOTIFY_FRIEND_MESSAGE,
|
||||
NOTIFY_WHISPER,
|
||||
NOTIFY_WHISPER_OTHER_WINDOW,
|
||||
NOTIFY_LOBBY_JOIN,
|
||||
NOTIFY_LOBBY_QUIT,
|
||||
NOTIFY_COUNT
|
||||
};
|
||||
|
||||
void do_notify(t_notify_mode mode) { do_notify(mode, "", ""); }
|
||||
void do_notify(t_notify_mode mode, const std::string & sender, const std::string & message);
|
||||
void do_notify(t_notify_mode mode, const std::string & sender, const std::string & message) { do_mp_notify(mode, sender, message); }
|
||||
|
||||
protected:
|
||||
/** inherited form chat_handler */
|
||||
virtual void send_chat_message(const std::string& message,
|
||||
bool /*allies_only*/) override;
|
||||
|
||||
virtual void user_relation_changed(const std::string& name) override;
|
||||
|
||||
/** inherited from chat_handler */
|
||||
virtual void add_chat_message(const time_t& time,
|
||||
const std::string& speaker,
|
||||
int side,
|
||||
const std::string& message,
|
||||
events::chat_handler::MESSAGE_TYPE type
|
||||
= events::chat_handler::MESSAGE_PRIVATE) override;
|
||||
|
||||
/** inherited from chat_handler */
|
||||
virtual void add_whisper_sent(const std::string& receiver,
|
||||
const std::string& message) override;
|
||||
|
||||
/** inherited from chat_handler */
|
||||
virtual void add_whisper_received(const std::string& sender,
|
||||
const std::string& message) override;
|
||||
|
||||
/** inherited from chat_handler */
|
||||
virtual void add_chat_room_message_sent(const std::string& room,
|
||||
const std::string& message) override;
|
||||
|
||||
/** inherited from chat_handler */
|
||||
virtual void add_chat_room_message_received(const std::string& room,
|
||||
const std::string& speaker,
|
||||
const std::string& message) override;
|
||||
|
||||
private:
|
||||
void update_selected_game();
|
||||
|
||||
/**
|
||||
* Append some text to the active chat log
|
||||
*/
|
||||
void append_to_chatbox(const std::string& text, const bool force_scroll = false);
|
||||
|
||||
/**
|
||||
* Append some text to the chat log for window "id"
|
||||
*/
|
||||
void append_to_chatbox(const std::string& text, size_t id, const bool force_scroll = false);
|
||||
|
||||
/**
|
||||
* Result flag for interfacing with other MP dialogs
|
||||
*/
|
||||
legacy_result legacy_result_;
|
||||
|
||||
/**
|
||||
* Get the room* corresponding to the currently active window, or nullptr
|
||||
* if a whisper window is active at the moment
|
||||
*/
|
||||
room_info* active_window_room();
|
||||
|
||||
/**
|
||||
* Check if a room window for "room" is open, if open_new is true
|
||||
* then it will be created if not found.
|
||||
* @return valid ptr if the window was found or added, null otherwise
|
||||
*/
|
||||
tlobby_chat_window* room_window_open(const std::string& room,
|
||||
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 found.
|
||||
* @return valid ptr if the window was found or added, null otherwise
|
||||
*/
|
||||
tlobby_chat_window* whisper_window_open(const std::string& name,
|
||||
bool open_new);
|
||||
|
||||
/**
|
||||
* Helper function to find and open a new window, used by *_window_open
|
||||
*/
|
||||
tlobby_chat_window*
|
||||
search_create_window(const std::string& name, bool whisper, bool open_new);
|
||||
|
||||
/**
|
||||
* @return true if the whisper window for "name" is the active window
|
||||
*/
|
||||
bool whisper_window_active(const std::string& name);
|
||||
|
||||
/**
|
||||
* @return true if the room window for "room" is the active window
|
||||
*/
|
||||
bool room_window_active(const std::string& room);
|
||||
|
||||
/**
|
||||
* Mark the whisper window for "name" as having one more pending message
|
||||
*/
|
||||
void increment_waiting_whsipers(const std::string& name);
|
||||
|
||||
/**
|
||||
* Mark the room window for "room" as having one more pending message
|
||||
*/
|
||||
void increment_waiting_messages(const std::string& room);
|
||||
|
||||
/**
|
||||
* Add a whisper message to the whisper window
|
||||
*/
|
||||
void add_whisper_window_whisper(const std::string& sender,
|
||||
const std::string& message);
|
||||
|
||||
/**
|
||||
* Add a whisper message to the current window which is not the whisper
|
||||
* window
|
||||
* for "name".
|
||||
*/
|
||||
void add_active_window_whisper(const std::string& sender,
|
||||
const std::string& message,
|
||||
const bool force_scroll = false);
|
||||
|
||||
/**
|
||||
* Add a message to the window for room "room"
|
||||
*/
|
||||
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"
|
||||
*/
|
||||
void add_active_window_message(const std::string& sender,
|
||||
const std::string& message,
|
||||
const bool force_scroll = false);
|
||||
|
||||
/**
|
||||
* Switch to the window given by a valid pointer (e.g. received from a call
|
||||
* to *_window_open)
|
||||
*/
|
||||
void switch_to_window(tlobby_chat_window* t);
|
||||
|
||||
void switch_to_window(size_t id);
|
||||
|
||||
void active_window_changed();
|
||||
|
||||
void close_active_window();
|
||||
|
||||
void close_window(size_t idx);
|
||||
|
||||
|
||||
/**
|
||||
* Network polling callback
|
||||
*/
|
||||
|
@ -286,18 +130,10 @@ private:
|
|||
|
||||
void process_network_data(const config& data);
|
||||
|
||||
void process_message(const config& data, bool whisper = false);
|
||||
|
||||
void process_gamelist(const config& data);
|
||||
|
||||
void process_gamelist_diff(const config& data);
|
||||
|
||||
void process_room_join(const config& data);
|
||||
|
||||
void process_room_part(const config& data);
|
||||
|
||||
void process_room_query_response(const config& data);
|
||||
|
||||
void join_global_button_callback(twindow& window);
|
||||
|
||||
void observe_global_button_callback(twindow& window);
|
||||
|
@ -312,27 +148,12 @@ private:
|
|||
*/
|
||||
bool do_game_join(int idx, bool observe);
|
||||
|
||||
void send_message_button_callback(twindow& window);
|
||||
|
||||
void send_message_to_active_window(const std::string& input);
|
||||
|
||||
void close_window_button_callback(tlobby_chat_window& chat_window, bool& handled, bool& halt);
|
||||
|
||||
void create_button_callback(twindow& window);
|
||||
|
||||
void show_preferences_button_callback(twindow& window);
|
||||
|
||||
void refresh_button_callback(twindow& window);
|
||||
|
||||
void quit_button_callback(twindow& window);
|
||||
|
||||
void room_switch_callback(twindow& window);
|
||||
|
||||
void chat_input_keypress_callback(bool& handled,
|
||||
bool& halt,
|
||||
const SDLKey key,
|
||||
twindow& window);
|
||||
|
||||
void game_filter_reload();
|
||||
|
||||
void game_filter_change_callback(twidget& widget);
|
||||
|
@ -367,23 +188,13 @@ private:
|
|||
|
||||
tlistbox* gamelistbox_;
|
||||
|
||||
tlistbox* roomlistbox_;
|
||||
|
||||
tmulti_page* chat_log_container_;
|
||||
|
||||
ttext_box* chat_input_;
|
||||
|
||||
twindow* window_;
|
||||
|
||||
lobby_info& lobby_info_;
|
||||
|
||||
std::function<void()> preferences_callback_;
|
||||
tmp_chatbox* chatbox_;
|
||||
|
||||
/**
|
||||
* This represents the open chat windows (rooms and whispers at the moment)
|
||||
* with 1 to 1 correspondence to what the user sees in the interface
|
||||
*/
|
||||
std::vector<tlobby_chat_window> open_windows_;
|
||||
std::function<void()> preferences_callback_;
|
||||
|
||||
size_t active_window_;
|
||||
|
||||
|
|
819
src/gui/widgets/mp_chatbox.cpp
Normal file
819
src/gui/widgets/mp_chatbox.cpp
Normal file
|
@ -0,0 +1,819 @@
|
|||
/*
|
||||
Copyright (C) 2016 The Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include "gui/widgets/mp_chatbox.hpp"
|
||||
|
||||
#include "gui/auxiliary/find_widget.hpp"
|
||||
|
||||
#include "gui/core/register_widget.hpp"
|
||||
#include "gui/widgets/button.hpp"
|
||||
#include "gui/widgets/listbox.hpp"
|
||||
#include "gui/widgets/label.hpp"
|
||||
#include "gui/widgets/text_box.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/scroll_label.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
#include "gui/widgets/image.hpp"
|
||||
#include "gui/widgets/multi_page.hpp"
|
||||
|
||||
#include "formatter.hpp"
|
||||
#include "formula/string_utils.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "marked-up_text.hpp"
|
||||
#include "wesnothd_connection.hpp"
|
||||
#include "config_assign.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "lobby_preferences.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
static lg::log_domain log_network("network");
|
||||
#define DBG_NW LOG_STREAM(debug, log_network)
|
||||
#define LOG_NW LOG_STREAM(info, log_network)
|
||||
#define ERR_NW LOG_STREAM(err, log_network)
|
||||
|
||||
static lg::log_domain log_engine("engine");
|
||||
#define LOG_NG LOG_STREAM(info, log_engine)
|
||||
#define ERR_NG LOG_STREAM(err, log_engine)
|
||||
|
||||
static lg::log_domain log_config("config");
|
||||
#define ERR_CF LOG_STREAM(err, log_config)
|
||||
|
||||
static lg::log_domain log_lobby("lobby");
|
||||
#define DBG_LB LOG_STREAM(debug, log_lobby)
|
||||
#define LOG_LB LOG_STREAM(info, log_lobby)
|
||||
#define ERR_LB LOG_STREAM(err, log_lobby)
|
||||
#define SCOPE_LB log_scope2(log_lobby, __func__)
|
||||
|
||||
namespace
|
||||
{
|
||||
void add_label_data(std::map<std::string, string_map>& map,
|
||||
const std::string& key,
|
||||
const std::string& label)
|
||||
{
|
||||
string_map item;
|
||||
item["label"] = label;
|
||||
item["use_markup"] = "true";
|
||||
map.emplace(key, item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
||||
// ------------ WIDGET -----------{
|
||||
|
||||
REGISTER_WIDGET(mp_chatbox)
|
||||
|
||||
tmp_chatbox::tmp_chatbox()
|
||||
: tcontainer_(1)
|
||||
, roomlistbox_(nullptr)
|
||||
, chat_log_container_(nullptr)
|
||||
, chat_input_(nullptr)
|
||||
, active_window_(0)
|
||||
, active_window_changed_callback_()
|
||||
, lobby_info_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void tmp_chatbox::active_window_changed()
|
||||
{
|
||||
tlobby_chat_window& t = open_windows_[active_window_];
|
||||
|
||||
// clear pending messages notification in room listbox
|
||||
tgrid* grid = roomlistbox_->get_row_grid(active_window_);
|
||||
find_widget<timage>(grid, "pending_messages", false).set_visible(twidget::tvisible::hidden);
|
||||
t.pending_messages = 0;
|
||||
if (active_window_changed_callback_) {
|
||||
active_window_changed_callback_();
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::switch_to_window(tlobby_chat_window* t)
|
||||
{
|
||||
switch_to_window(t - &open_windows_[0]);
|
||||
}
|
||||
|
||||
void tmp_chatbox::switch_to_window(size_t id)
|
||||
{
|
||||
active_window_ = id;
|
||||
assert(active_window_ < open_windows_.size());
|
||||
chat_log_container_->select_page(active_window_);
|
||||
roomlistbox_->select_row(active_window_);
|
||||
active_window_changed();
|
||||
}
|
||||
|
||||
void tmp_chatbox::finalize_setup()
|
||||
{
|
||||
|
||||
roomlistbox_ = find_widget<tlistbox>(this, "room_list", false, true);
|
||||
|
||||
chat_log_container_ = find_widget<tmulti_page>(this, "chat_log_container", false, true);
|
||||
|
||||
chat_input_ = find_widget<ttext_box>(this, "chat_input", false, true);
|
||||
|
||||
roomlistbox_->set_callback_value_change(
|
||||
[this](twidget&) { switch_to_window(roomlistbox_->get_selected_row()); });
|
||||
|
||||
connect_signal_pre_key_press(
|
||||
*chat_input_,
|
||||
std::bind(&tmp_chatbox::chat_input_keypress_callback,
|
||||
this,
|
||||
_3,
|
||||
_4,
|
||||
_5));
|
||||
|
||||
}
|
||||
|
||||
void tmp_chatbox::send_message_button_callback()
|
||||
{
|
||||
const std::string& input = chat_input_->get_value();
|
||||
if (input.empty())
|
||||
return;
|
||||
if (input[0] == '/') {
|
||||
// TODO: refactor do_speak so it uses context information about
|
||||
// opened window, so e.g. /ignore in a whisper session ignores
|
||||
// the other party without having to specify it's nick.
|
||||
//chat_handler::do_speak(input);
|
||||
}
|
||||
else {
|
||||
tlobby_chat_window& t = open_windows_[active_window_];
|
||||
if (t.whisper) {
|
||||
send_whisper(t.name, input);
|
||||
add_whisper_sent(t.name, input);
|
||||
}
|
||||
else {
|
||||
send_chat_room_message(t.name, input);
|
||||
add_chat_room_message_sent(t.name, input);
|
||||
}
|
||||
}
|
||||
chat_input_->save_to_history();
|
||||
chat_input_->set_value("");
|
||||
}
|
||||
|
||||
|
||||
void tmp_chatbox::chat_input_keypress_callback(bool& handled, bool& halt, const SDLKey key)
|
||||
{
|
||||
if (key == SDLK_RETURN || key == SDLK_KP_ENTER) {
|
||||
send_message_button_callback();
|
||||
handled = true;
|
||||
halt = true;
|
||||
}
|
||||
else if (key == SDLK_TAB) {
|
||||
std::string text = chat_input_->get_value();
|
||||
|
||||
std::vector<std::string> matches;
|
||||
for (const auto & ui : lobby_info().users())
|
||||
{
|
||||
if (ui.name != preferences::login()) {
|
||||
matches.push_back(ui.name);
|
||||
}
|
||||
}
|
||||
|
||||
const bool line_start = utils::word_completion(text, matches);
|
||||
|
||||
if (matches.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (matches.size() == 1) {
|
||||
text.append(line_start ? ": " : " ");
|
||||
}
|
||||
else {
|
||||
std::string completion_list = utils::join(matches, " ");
|
||||
append_to_chatbox(completion_list);
|
||||
}
|
||||
chat_input_->set_value(text);
|
||||
handled = true;
|
||||
halt = true;
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::append_to_chatbox(const std::string& text, const bool force_scroll)
|
||||
{
|
||||
append_to_chatbox(text, active_window_, force_scroll);
|
||||
}
|
||||
|
||||
void tmp_chatbox::append_to_chatbox(const std::string& text, size_t id, const bool force_scroll)
|
||||
{
|
||||
tgrid& grid = chat_log_container_->page_grid(id);
|
||||
tscroll_label& log = find_widget<tscroll_label>(&grid, "log_text", false);
|
||||
const bool chatbox_at_end = log.vertical_scrollbar_at_end();
|
||||
const unsigned chatbox_position = log.get_vertical_scrollbar_item_position();
|
||||
log.set_use_markup(true);
|
||||
log.set_label(log.label() + "\n" +
|
||||
"<span color='#bcb088'>" + preferences::get_chat_timestamp(time(0)) + text + "</span>");
|
||||
|
||||
if (chatbox_at_end || force_scroll) {
|
||||
log.scroll_vertical_scrollbar(tscrollbar_::END);
|
||||
}
|
||||
else {
|
||||
log.set_vertical_scrollbar_item_position(chatbox_position);
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::set_active(const bool /*active*/)
|
||||
{
|
||||
/* DO NOTHING */
|
||||
}
|
||||
|
||||
bool tmp_chatbox::get_active() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
const std::string& tmp_chatbox::get_control_type() const
|
||||
{
|
||||
static const std::string type = "mp_chatbox";
|
||||
return type;
|
||||
}
|
||||
|
||||
void tmp_chatbox::set_self_active(const bool /*active*/)
|
||||
{
|
||||
/* DO NOTHING */
|
||||
}
|
||||
|
||||
|
||||
void tmp_chatbox::send_chat_message(const std::string& message,
|
||||
bool /*allies_only*/)
|
||||
{
|
||||
::config c = config_of("message", config_of("message", message)("sender", preferences::login()));
|
||||
add_chat_message(time(nullptr), preferences::login(), 0, message); // local
|
||||
// echo
|
||||
lobby_info().wesnothd_connection().send_data(c);
|
||||
}
|
||||
|
||||
void tmp_chatbox::user_relation_changed(const std::string& /*name*/)
|
||||
{
|
||||
if (active_window_changed_callback_) {
|
||||
active_window_changed_callback_();
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::add_chat_message(const time_t& /*time*/,
|
||||
const std::string& speaker,
|
||||
int /*side*/,
|
||||
const std::string& message,
|
||||
events::chat_handler::MESSAGE_TYPE /*type*/)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>" << speaker << ":</b> ";
|
||||
ss << font::escape_text(message);
|
||||
append_to_chatbox(ss.str());
|
||||
}
|
||||
|
||||
|
||||
void tmp_chatbox::add_whisper_sent(const std::string& receiver,
|
||||
const std::string& message)
|
||||
{
|
||||
if (whisper_window_active(receiver)) {
|
||||
add_active_window_message(preferences::login(), message, true);
|
||||
}
|
||||
else if (tlobby_chat_window* t = whisper_window_open(
|
||||
receiver, preferences::auto_open_whisper_windows())) {
|
||||
switch_to_window(t);
|
||||
add_active_window_message(preferences::login(), message, true);
|
||||
}
|
||||
else {
|
||||
utils::string_map symbols;
|
||||
symbols["receiver"] = receiver;
|
||||
add_active_window_whisper(VGETTEXT("whisper to $receiver", symbols),
|
||||
message, true);
|
||||
}
|
||||
lobby_info().get_whisper_log(receiver)
|
||||
.add_message(preferences::login(), message);
|
||||
}
|
||||
|
||||
void tmp_chatbox::add_whisper_received(const std::string& sender,
|
||||
const std::string& message)
|
||||
{
|
||||
bool can_go_to_active = !preferences::whisper_friends_only()
|
||||
|| preferences::is_friend(sender);
|
||||
bool can_open_new = preferences::auto_open_whisper_windows()
|
||||
&& can_go_to_active;
|
||||
lobby_info().get_whisper_log(sender).add_message(sender, message);
|
||||
if (whisper_window_open(sender, can_open_new)) {
|
||||
if (whisper_window_active(sender)) {
|
||||
add_active_window_message(sender, message);
|
||||
do_notify(NOTIFY_WHISPER, sender, message);
|
||||
}
|
||||
else {
|
||||
add_whisper_window_whisper(sender, message);
|
||||
increment_waiting_whsipers(sender);
|
||||
do_notify(NOTIFY_WHISPER_OTHER_WINDOW, sender, message);
|
||||
}
|
||||
}
|
||||
else if (can_go_to_active) {
|
||||
add_active_window_whisper(sender, message);
|
||||
do_notify(NOTIFY_WHISPER, sender, message);
|
||||
}
|
||||
else {
|
||||
LOG_LB << "Ignoring whisper from " << sender << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::add_chat_room_message_sent(const std::string& room,
|
||||
const std::string& message)
|
||||
{
|
||||
// do not open room window here, player should be in the room before sending
|
||||
// messages yo it should be allowed to happen
|
||||
if (tlobby_chat_window* t = room_window_open(room, false)) {
|
||||
room_info* ri = lobby_info().get_room(room);
|
||||
assert(ri);
|
||||
if (!room_window_active(room)) {
|
||||
switch_to_window(t);
|
||||
}
|
||||
ri->log().add_message(preferences::login(), message);
|
||||
add_active_window_message(preferences::login(), message, true);
|
||||
}
|
||||
else {
|
||||
LOG_LB << "Cannot add sent message to ui for room " << room
|
||||
<< ", player not in the room\n";
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::add_chat_room_message_received(const std::string& room,
|
||||
const std::string& speaker,
|
||||
const std::string& message)
|
||||
{
|
||||
if (room_info* ri = lobby_info().get_room(room)) {
|
||||
t_notify_mode notify_mode = NOTIFY_NONE;
|
||||
ri->log().add_message(speaker, message);
|
||||
if (room_window_active(room)) {
|
||||
add_active_window_message(speaker, message);
|
||||
notify_mode = NOTIFY_MESSAGE;
|
||||
}
|
||||
else {
|
||||
add_room_window_message(room, speaker, message);
|
||||
increment_waiting_messages(room);
|
||||
notify_mode = NOTIFY_MESSAGE_OTHER_WINDOW;
|
||||
}
|
||||
if (speaker == "server") {
|
||||
notify_mode = NOTIFY_SERVER_MESSAGE;
|
||||
}
|
||||
else if (utils::word_match(message, preferences::login())) {
|
||||
notify_mode = NOTIFY_OWN_NICK;
|
||||
}
|
||||
else if (preferences::is_friend(speaker)) {
|
||||
notify_mode = NOTIFY_FRIEND_MESSAGE;
|
||||
}
|
||||
do_notify(notify_mode, speaker, message);
|
||||
}
|
||||
else {
|
||||
LOG_LB << "Discarding message to room " << room << " from " << speaker
|
||||
<< " (room not open)\n";
|
||||
}
|
||||
}
|
||||
bool tmp_chatbox::whisper_window_active(const std::string& name)
|
||||
{
|
||||
const tlobby_chat_window& t = open_windows_[active_window_];
|
||||
return t.name == name && t.whisper == true;
|
||||
}
|
||||
|
||||
bool tmp_chatbox::room_window_active(const std::string& room)
|
||||
{
|
||||
const tlobby_chat_window& t = open_windows_[active_window_];
|
||||
return t.name == room && t.whisper == false;
|
||||
}
|
||||
|
||||
tlobby_chat_window* tmp_chatbox::room_window_open(const std::string& room,
|
||||
bool open_new)
|
||||
{
|
||||
return search_create_window(room, false, open_new);
|
||||
}
|
||||
|
||||
tlobby_chat_window* tmp_chatbox::whisper_window_open(const std::string& name,
|
||||
bool open_new)
|
||||
{
|
||||
return search_create_window(name, true, open_new);
|
||||
}
|
||||
|
||||
|
||||
tlobby_chat_window* tmp_chatbox::search_create_window(const std::string& name,
|
||||
bool whisper,
|
||||
bool open_new)
|
||||
{
|
||||
for (auto & t : open_windows_) {
|
||||
if (t.name == name && t.whisper == whisper)
|
||||
return &t;
|
||||
}
|
||||
|
||||
if (open_new) {
|
||||
open_windows_.push_back(tlobby_chat_window(name, whisper));
|
||||
std::map<std::string, string_map> data;
|
||||
utils::string_map symbols;
|
||||
symbols["name"] = name;
|
||||
if (whisper) {
|
||||
add_label_data(data, "log_text",
|
||||
VGETTEXT("Whisper session with $name started. "
|
||||
"If you do not want to receive messages "
|
||||
"from this user, "
|
||||
"type /ignore $name\n",
|
||||
symbols));
|
||||
}
|
||||
else {
|
||||
add_label_data(data, "log_text", VGETTEXT("<i>Room $name joined</i>", symbols));
|
||||
lobby_info().open_room(name);
|
||||
}
|
||||
|
||||
chat_log_container_->add_page(data);
|
||||
std::map<std::string, string_map> data2;
|
||||
add_label_data(data2, "room", whisper ? font::escape_text("<" + name + ">") : name);
|
||||
tgrid* row_grid = &roomlistbox_->add_row(data2);
|
||||
|
||||
tbutton& close_button = find_widget<tbutton>(row_grid, "close_window", false);
|
||||
connect_signal_mouse_left_click(close_button,
|
||||
std::bind(&tmp_chatbox::close_window_button_callback, this, open_windows_.back(),
|
||||
_3, _4));
|
||||
|
||||
if (name == "lobby") {
|
||||
close_button.set_visible(tcontrol::tvisible::hidden);
|
||||
}
|
||||
|
||||
return &open_windows_.back();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void tmp_chatbox::close_window_button_callback(tlobby_chat_window& chat_window, bool& handled, bool& halt)
|
||||
{
|
||||
const int index = std::find_if(open_windows_.begin(), open_windows_.end(), [&chat_window](const tlobby_chat_window& room) {
|
||||
return room.name == chat_window.name;
|
||||
}) - open_windows_.begin();
|
||||
|
||||
close_window(index);
|
||||
|
||||
handled = true;
|
||||
halt = true;
|
||||
}
|
||||
|
||||
void tmp_chatbox::send_to_server(const ::config& cfg)
|
||||
{
|
||||
lobby_info().wesnothd_connection().send_data(cfg);
|
||||
}
|
||||
|
||||
|
||||
void tmp_chatbox::increment_waiting_whsipers(const std::string& name)
|
||||
{
|
||||
if (tlobby_chat_window* t = whisper_window_open(name, false)) {
|
||||
t->pending_messages++;
|
||||
if (t->pending_messages == 1) {
|
||||
DBG_LB << "do whisper pending mark row " << (t - &open_windows_[0])
|
||||
<< " with " << t->name << "\n";
|
||||
tgrid* grid = roomlistbox_->get_row_grid(t - &open_windows_[0]);
|
||||
// this breaks for some reason
|
||||
// tlabel& label = grid->get_widget<tlabel>("room", false);
|
||||
// label.set_use_markup(true);
|
||||
// label.set_label(colorize("<" + t->name + ">", "red"));
|
||||
find_widget<timage>(grid, "pending_messages", false)
|
||||
.set_visible(twidget::tvisible::visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::increment_waiting_messages(const std::string& room)
|
||||
{
|
||||
if (tlobby_chat_window* t = room_window_open(room, false)) {
|
||||
t->pending_messages++;
|
||||
if (t->pending_messages == 1) {
|
||||
int idx = t - &open_windows_[0];
|
||||
DBG_LB << "do room pending mark row " << idx << " with " << t->name
|
||||
<< "\n";
|
||||
tgrid* grid = roomlistbox_->get_row_grid(idx);
|
||||
// this breaks for some reason
|
||||
// tlabel& label = grid->get_widget<tlabel>("room", false);
|
||||
// label.set_use_markup(true);
|
||||
// label.set_label(colorize(t->name, "red"));
|
||||
find_widget<timage>(grid, "pending_messages", false)
|
||||
.set_visible(twidget::tvisible::visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::add_whisper_window_whisper(const std::string& sender,
|
||||
const std::string& message)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>" << sender << ":</b> " << font::escape_text(message);
|
||||
tlobby_chat_window* t = whisper_window_open(sender, false);
|
||||
if (!t) {
|
||||
ERR_LB << "Whisper window not open in add_whisper_window_whisper for "
|
||||
<< sender << "\n";
|
||||
return;
|
||||
}
|
||||
append_to_chatbox(ss.str(), t - &open_windows_[0], false);
|
||||
}
|
||||
|
||||
void tmp_chatbox::add_active_window_whisper(const std::string& sender,
|
||||
const std::string& message,
|
||||
const bool force_scroll)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>"
|
||||
<< "whisper: " << sender << ":</b> " << font::escape_text(message);
|
||||
append_to_chatbox(ss.str(), force_scroll);
|
||||
}
|
||||
|
||||
void tmp_chatbox::close_window(size_t idx)
|
||||
{
|
||||
const tlobby_chat_window& t = open_windows_[idx];
|
||||
bool active_changed = idx == active_window_;
|
||||
DBG_LB << "Close window " << idx << " - " << t.name << "\n";
|
||||
|
||||
if ((t.name == "lobby" && t.whisper == false) || open_windows_.size() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.whisper == false) {
|
||||
// closing a room window -- send a part to the server
|
||||
::config data, msg;
|
||||
msg["room"] = t.name;
|
||||
msg["player"] = preferences::login();
|
||||
data.add_child("room_part", msg);
|
||||
send_to_server(data);
|
||||
}
|
||||
|
||||
if (active_window_ == open_windows_.size() - 1) {
|
||||
active_window_--;
|
||||
}
|
||||
|
||||
if (t.whisper) {
|
||||
lobby_info().get_whisper_log(t.name).clear();
|
||||
}
|
||||
else {
|
||||
lobby_info().close_room(t.name);
|
||||
}
|
||||
|
||||
open_windows_.erase(open_windows_.begin() + idx);
|
||||
roomlistbox_->remove_row(idx);
|
||||
roomlistbox_->select_row(active_window_);
|
||||
chat_log_container_->remove_page(idx);
|
||||
chat_log_container_->select_page(active_window_);
|
||||
if (active_changed)
|
||||
active_window_changed();
|
||||
}
|
||||
|
||||
void tmp_chatbox::add_room_window_message(const std::string& room,
|
||||
const std::string& sender,
|
||||
const std::string& message)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>" << sender << ":</b> " << font::escape_text(message);
|
||||
tlobby_chat_window* t = room_window_open(room, false);
|
||||
if (!t) {
|
||||
ERR_LB << "Room window not open in add_room_window_message for " << room
|
||||
<< "\n";
|
||||
return;
|
||||
}
|
||||
append_to_chatbox(ss.str(), t - &open_windows_[0], false);
|
||||
}
|
||||
|
||||
void tmp_chatbox::add_active_window_message(const std::string& sender,
|
||||
const std::string& message,
|
||||
const bool force_scroll)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "<b>" << sender << ":</b> " << font::escape_text(message);
|
||||
append_to_chatbox(ss.str(), force_scroll);
|
||||
}
|
||||
|
||||
|
||||
room_info* tmp_chatbox::active_window_room()
|
||||
{
|
||||
const tlobby_chat_window& t = open_windows_[active_window_];
|
||||
if (t.whisper)
|
||||
return nullptr;
|
||||
return lobby_info().get_room(t.name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tmp_chatbox::process_room_join(const ::config& data)
|
||||
{
|
||||
const std::string& room = data["room"];
|
||||
const std::string& player = data["player"];
|
||||
room_info* r = lobby_info().get_room(room);
|
||||
DBG_LB << "room join: " << room << " " << player << " "
|
||||
<< static_cast<void*>(r) << "\n";
|
||||
|
||||
if (r) {
|
||||
if (player == preferences::login()) {
|
||||
if (const auto& members = data.child("members")) {
|
||||
r->process_room_members(members);
|
||||
}
|
||||
}
|
||||
else {
|
||||
r->add_member(player);
|
||||
/* TODO: add/use preference */
|
||||
utils::string_map symbols;
|
||||
symbols["player"] = player;
|
||||
add_room_window_message(
|
||||
room,
|
||||
"server",
|
||||
VGETTEXT("$player has entered the room", symbols));
|
||||
}
|
||||
if (r == active_window_room()) {
|
||||
active_window_changed_callback_();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (player == preferences::login()) {
|
||||
tlobby_chat_window* t = room_window_open(room, true);
|
||||
lobby_info().open_room(room);
|
||||
r = lobby_info().get_room(room);
|
||||
assert(r);
|
||||
if (const auto& members = data.child("members")) {
|
||||
r->process_room_members(members);
|
||||
}
|
||||
switch_to_window(t);
|
||||
|
||||
const std::string& topic = data["topic"];
|
||||
if (!topic.empty()) {
|
||||
add_chat_room_message_received(
|
||||
"room", "server", room + ": " + topic);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_LB << "Discarding join info for a room the player is not in\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::process_room_part(const ::config& data)
|
||||
{
|
||||
// todo close room window when the part message is sent
|
||||
const std::string& room = data["room"];
|
||||
const std::string& player = data["player"];
|
||||
DBG_LB << "Room part: " << room << " " << player << "\n";
|
||||
room_info* r = lobby_info().get_room(room);
|
||||
if (r) {
|
||||
r->remove_member(player);
|
||||
/* TODO: add/use preference */
|
||||
utils::string_map symbols;
|
||||
symbols["player"] = player;
|
||||
add_room_window_message(
|
||||
room, "server", VGETTEXT("$player has left the room", symbols));
|
||||
if (active_window_room() == r) {
|
||||
active_window_changed_callback_();
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_LB << "Discarding part info for a room the player is not in\n";
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::process_room_query_response(const ::config& data)
|
||||
{
|
||||
const std::string& room = data["room"];
|
||||
const std::string& message = data["message"];
|
||||
DBG_LB << "room query response: " << room << " " << message << "\n";
|
||||
if (room.empty()) {
|
||||
if (!message.empty()) {
|
||||
add_active_window_message("server", message);
|
||||
}
|
||||
if (const ::config& rooms = data.child("rooms")) {
|
||||
// TODO: this should really open a nice join room dialog instead
|
||||
std::stringstream ss;
|
||||
ss << "Rooms:";
|
||||
for (const auto & r : rooms.child_range("room"))
|
||||
{
|
||||
ss << " " << r["name"];
|
||||
}
|
||||
add_active_window_message("server", ss.str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (room_window_open(room, false)) {
|
||||
if (!message.empty()) {
|
||||
add_chat_room_message_received(room, "server", message);
|
||||
}
|
||||
if (const ::config& members = data.child("members")) {
|
||||
room_info* r = lobby_info().get_room(room);
|
||||
assert(r);
|
||||
r->process_room_members(members);
|
||||
if (r == active_window_room()) {
|
||||
active_window_changed_callback_();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!message.empty()) {
|
||||
add_active_window_message("server", room + ": " + message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_chatbox::process_message(const ::config& data, bool whisper /*= false*/)
|
||||
{
|
||||
std::string sender = data["sender"];
|
||||
DBG_LB << "process message from " << sender << " " << (whisper ? "(w)" : "")
|
||||
<< ", len " << data["message"].str().size() << '\n';
|
||||
if (preferences::is_ignored(sender))
|
||||
return;
|
||||
const std::string& message = data["message"];
|
||||
preferences::parse_admin_authentication(sender, message);
|
||||
if (whisper) {
|
||||
add_whisper_received(sender, message);
|
||||
}
|
||||
else {
|
||||
std::string room = data["room"];
|
||||
if (room.empty()) {
|
||||
LOG_LB << "Message without a room from " << sender
|
||||
<< ", assuming lobby\n";
|
||||
room = "lobby";
|
||||
}
|
||||
add_chat_room_message_received(room, sender, message);
|
||||
}
|
||||
}
|
||||
|
||||
bool tmp_chatbox::process_network_data(const ::config& data)
|
||||
{
|
||||
|
||||
if (const ::config& c = data.child("message")) {
|
||||
process_message(c);
|
||||
}
|
||||
else if (const ::config& c = data.child("whisper")) {
|
||||
process_message(c, true);
|
||||
}
|
||||
else if (const ::config& c = data.child("room_join")) {
|
||||
process_room_join(c);
|
||||
}
|
||||
else if (const ::config& c = data.child("room_part")) {
|
||||
process_room_part(c);
|
||||
}
|
||||
else if (const ::config& c = data.child("room_query_response")) {
|
||||
process_room_query_response(c);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// }---------- DEFINITION ---------{
|
||||
|
||||
tmp_chatbox_definition::tmp_chatbox_definition(const config& cfg)
|
||||
: tcontrol_definition(cfg)
|
||||
{
|
||||
load_resolutions<tresolution>(cfg);
|
||||
}
|
||||
|
||||
tmp_chatbox_definition::tresolution::tresolution(const config& cfg)
|
||||
: tresolution_definition_(cfg), grid()
|
||||
{
|
||||
state.push_back(tstate_definition(cfg.child("background")));
|
||||
state.push_back(tstate_definition(cfg.child("foreground")));
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<tbuilder_grid>(child);
|
||||
}
|
||||
// }---------- BUILDER -----------{
|
||||
|
||||
namespace implementation
|
||||
{
|
||||
|
||||
tbuilder_mp_chatbox::tbuilder_mp_chatbox(const config& cfg)
|
||||
: tbuilder_control(cfg)
|
||||
{
|
||||
}
|
||||
|
||||
twidget* tbuilder_mp_chatbox::build() const
|
||||
{
|
||||
tmp_chatbox* widget = new tmp_chatbox();
|
||||
|
||||
init_control(widget);
|
||||
|
||||
DBG_GUI_G << "Window builder: placed unit preview pane '" << id
|
||||
<< "' with definition '" << definition << "'.\n";
|
||||
|
||||
std::shared_ptr<const tmp_chatbox_definition::tresolution> conf
|
||||
= std::static_pointer_cast<
|
||||
const tmp_chatbox_definition::tresolution>(widget->config());
|
||||
|
||||
assert(conf);
|
||||
|
||||
widget->init_grid(conf->grid);
|
||||
widget->finalize_setup();
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
// }------------ END --------------
|
||||
|
||||
} // namespace gui2
|
290
src/gui/widgets/mp_chatbox.hpp
Normal file
290
src/gui/widgets/mp_chatbox.hpp
Normal file
|
@ -0,0 +1,290 @@
|
|||
/*
|
||||
Copyright (C) 2016 by the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gui/widgets/container.hpp"
|
||||
#include "gui/dialogs/lobby/data.hpp"
|
||||
#include "gui/dialogs/lobby/info.hpp"
|
||||
|
||||
#include "chat_events.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
class config;
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
||||
// ------------ WIDGET -----------{
|
||||
|
||||
class tbutton;
|
||||
class tlistbox;
|
||||
class tlabel;
|
||||
class tmulti_page;
|
||||
class ttext_box;
|
||||
|
||||
namespace implementation
|
||||
{
|
||||
struct tbuilder_mp_chatbox;
|
||||
}
|
||||
|
||||
|
||||
struct tlobby_chat_window
|
||||
{
|
||||
tlobby_chat_window(const std::string& name, bool whisper)
|
||||
: name(name), whisper(whisper), pending_messages(0)
|
||||
{
|
||||
}
|
||||
std::string name;
|
||||
bool whisper;
|
||||
int pending_messages;
|
||||
};
|
||||
|
||||
class tmp_chatbox : public tcontainer_, public events::chat_handler
|
||||
{
|
||||
friend struct implementation::tbuilder_mp_chatbox;
|
||||
|
||||
public:
|
||||
tmp_chatbox();
|
||||
|
||||
/** See @ref tcontrol::set_active. */
|
||||
virtual void set_active(const bool active) override;
|
||||
|
||||
/** See @ref tcontrol::get_active. */
|
||||
virtual bool get_active() const override;
|
||||
|
||||
/** See @ref tcontrol::get_state. */
|
||||
virtual unsigned get_state() const override { return 0; };
|
||||
|
||||
void send_to_server(const ::config& cfg) override;
|
||||
|
||||
void set_active_window_changed_callback(const std::function<void(void)>& f) { active_window_changed_callback_ = f; }
|
||||
|
||||
void set_lobby_info(lobby_info& i) { lobby_info_ = &i; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initializes the interneral sub-widget pointers.
|
||||
* Should be called when building the window, so the pointers
|
||||
* are initilized when set_displayed_type() is called.
|
||||
*/
|
||||
void finalize_setup();
|
||||
|
||||
virtual void user_relation_changed(const std::string& name) override;
|
||||
|
||||
/** inherited form chat_handler */
|
||||
virtual void add_chat_message(const time_t& 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 */
|
||||
virtual void add_whisper_sent(const std::string& receiver,
|
||||
const std::string& message) override;
|
||||
|
||||
/** inherited form chat_handler */
|
||||
virtual void add_whisper_received(const std::string& sender,
|
||||
const std::string& message) override;
|
||||
|
||||
/** inherited form chat_handler */
|
||||
virtual void add_chat_room_message_sent(const std::string& room,
|
||||
const std::string& message) override;
|
||||
|
||||
/** inherited form chat_handler */
|
||||
virtual void add_chat_room_message_received(const std::string& room,
|
||||
const std::string& speaker,
|
||||
const std::string& message) override;
|
||||
|
||||
|
||||
private:
|
||||
tlistbox* roomlistbox_;
|
||||
|
||||
tmulti_page* chat_log_container_;
|
||||
|
||||
ttext_box* chat_input_;
|
||||
|
||||
std::vector<tlobby_chat_window> open_windows_;
|
||||
|
||||
size_t active_window_;
|
||||
|
||||
std::function<void(void)> active_window_changed_callback_;
|
||||
|
||||
lobby_info* lobby_info_;
|
||||
|
||||
lobby_info& lobby_info() { return *lobby_info_; }
|
||||
|
||||
/** See @ref tcontrol::get_control_type. */
|
||||
virtual const std::string& get_control_type() const override;
|
||||
|
||||
/** See @ref tcontainer_::set_self_active. */
|
||||
virtual void set_self_active(const bool active) override;
|
||||
|
||||
void chat_input_keypress_callback(bool& handled, bool& halt, const SDLKey key);
|
||||
|
||||
void append_to_chatbox(const std::string& text, const bool force_scroll = false);
|
||||
|
||||
void append_to_chatbox(const std::string& text, size_t id, const bool force_scroll = false);
|
||||
/**
|
||||
* @return true if the whisper window for "name" is the active window
|
||||
*/
|
||||
bool whisper_window_active(const std::string& name);
|
||||
|
||||
/**
|
||||
* @return true if the room window for "room" is the active window
|
||||
*/
|
||||
bool room_window_active(const std::string& room);
|
||||
|
||||
/**
|
||||
* Mark the whisper window for "name" as having one more pending message
|
||||
*/
|
||||
void increment_waiting_whsipers(const std::string& name);
|
||||
|
||||
/**
|
||||
* Mark the room window for "room" as having one more pending message
|
||||
*/
|
||||
void increment_waiting_messages(const std::string& room);
|
||||
|
||||
/**
|
||||
* Add a whisper message to the whisper window
|
||||
*/
|
||||
void add_whisper_window_whisper(const std::string& sender,
|
||||
const std::string& message);
|
||||
|
||||
/**
|
||||
* Add a whisper message to the current window which is not the whisper
|
||||
* window
|
||||
* for "name".
|
||||
*/
|
||||
void add_active_window_whisper(const std::string& sender,
|
||||
const std::string& message,
|
||||
const bool force_scroll = false);
|
||||
|
||||
/**
|
||||
* Add a message to the window for room "room"
|
||||
*/
|
||||
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"
|
||||
*/
|
||||
void add_active_window_message(const std::string& sender,
|
||||
const std::string& message,
|
||||
const bool force_scroll = false);
|
||||
|
||||
void close_window(size_t idx);
|
||||
|
||||
void send_message_button_callback();
|
||||
|
||||
public:
|
||||
|
||||
/** inherited form chat_handler */
|
||||
virtual void send_chat_message(const std::string& message,
|
||||
bool /*allies_only*/) override;
|
||||
|
||||
/**
|
||||
* Switch to the window given by a valid pointer (e.g. received from a call
|
||||
* to *_window_open)
|
||||
*/
|
||||
void switch_to_window(tlobby_chat_window* t);
|
||||
|
||||
void switch_to_window(size_t id);
|
||||
|
||||
void active_window_changed();
|
||||
|
||||
/**
|
||||
* Get the room* corresponding to the currently active window, or nullptr
|
||||
* if a whisper window is active at the moment
|
||||
*/
|
||||
room_info* active_window_room();
|
||||
|
||||
/**
|
||||
* Check if a room window for "room" is open, if open_new is true
|
||||
* then it will be created if not found.
|
||||
* @return valid ptr if the window was found or added, null otherwise
|
||||
*/
|
||||
tlobby_chat_window* room_window_open(const std::string& room,
|
||||
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 found.
|
||||
* @return valid ptr if the window was found or added, null otherwise
|
||||
*/
|
||||
tlobby_chat_window* whisper_window_open(const std::string& name,
|
||||
bool open_new);
|
||||
|
||||
/**
|
||||
* Helper function to find and open a new window, used by *_window_open
|
||||
*/
|
||||
tlobby_chat_window* search_create_window(const std::string& name, bool whisper, bool open_new);
|
||||
|
||||
void do_notify(t_notify_mode mode) { do_notify(mode, "", ""); }
|
||||
void do_notify(t_notify_mode mode, const std::string & sender, const std::string & message) { do_mp_notify(mode, sender, message); }
|
||||
|
||||
void close_window_button_callback(tlobby_chat_window& chat_window, bool& handled, bool& halt);
|
||||
|
||||
|
||||
void process_room_join(const ::config& data);
|
||||
|
||||
void process_room_part(const ::config& data);
|
||||
|
||||
void process_room_query_response(const ::config& data);
|
||||
|
||||
void process_message(const ::config& data, bool whisper = false);
|
||||
|
||||
bool process_network_data(const ::config& data);
|
||||
};
|
||||
|
||||
// }---------- DEFINITION ---------{
|
||||
|
||||
struct tmp_chatbox_definition : public tcontrol_definition
|
||||
{
|
||||
|
||||
explicit tmp_chatbox_definition(const config& cfg);
|
||||
|
||||
struct tresolution : public tresolution_definition_
|
||||
{
|
||||
explicit tresolution(const config& cfg);
|
||||
|
||||
tbuilder_grid_ptr grid;
|
||||
};
|
||||
};
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
||||
namespace implementation
|
||||
{
|
||||
|
||||
struct tbuilder_mp_chatbox : public tbuilder_control
|
||||
{
|
||||
public:
|
||||
explicit tbuilder_mp_chatbox(const config& cfg);
|
||||
|
||||
using tbuilder_control::build;
|
||||
|
||||
twidget* build() const;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
// }------------ END --------------
|
||||
|
||||
} // namespace gui2
|
Loading…
Add table
Reference in a new issue