1 /* 2 Copyright (C) 2016 - 2018 by the Battle for Wesnoth Project https://www.wesnoth.org/ 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2 of the License, or 7 (at your option) any later version. 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY. 10 11 See the COPYING file for more details. 12 */ 13 14 #pragma once 15 16 #include "chat_events.hpp" 17 #include "chat_log.hpp" 18 #include "game_initialization/lobby_data.hpp" 19 #include "game_initialization/lobby_info.hpp" 20 #include "gui/widgets/container_base.hpp" 21 22 #include <map> 23 #include <string> 24 25 class config; 26 class wesnothd_connection; 27 28 namespace gui2 29 { 30 31 // ------------ WIDGET -----------{ 32 33 class listbox; 34 class multi_page; 35 class text_box; 36 37 namespace implementation 38 { 39 struct builder_chatbox; 40 } 41 42 struct lobby_chat_window 43 { lobby_chat_windowgui2::lobby_chat_window44 lobby_chat_window(const std::string& name, bool whisper) 45 : name(name), whisper(whisper), pending_messages(0) 46 { 47 } 48 49 std::string name; 50 bool whisper; 51 int pending_messages; 52 }; 53 54 class chatbox : public container_base, public events::chat_handler 55 { 56 friend struct implementation::builder_chatbox; 57 58 public: 59 explicit chatbox(const implementation::builder_chatbox& builder); 60 61 /** See @ref styled_widget::set_active. */ set_active(const bool)62 virtual void set_active(const bool /*active*/) override 63 { 64 /* DO NOTHING */ 65 } 66 67 /** See @ref styled_widget::get_active. */ get_active() const68 virtual bool get_active() const override 69 { 70 return true; 71 } 72 73 /** See @ref styled_widget::get_state. */ get_state() const74 virtual unsigned get_state() const override 75 { 76 return 0; 77 } 78 79 void send_to_server(const ::config& cfg) override; 80 81 /** @todo: remove */ set_active_window_changed_callback(const std::function<void (void)> & f)82 void set_active_window_changed_callback(const std::function<void(void)>& f) 83 { 84 active_window_changed_callback_ = f; 85 } 86 set_lobby_info(mp::lobby_info & i)87 void set_lobby_info(mp::lobby_info& i) 88 { 89 lobby_info_ = &i; 90 } 91 set_wesnothd_connection(wesnothd_connection & c)92 void set_wesnothd_connection(wesnothd_connection& c) 93 { 94 wesnothd_connection_ = &c; 95 } 96 97 void load_log(std::map<std::string, chatroom_log>& log, bool show_lobby); 98 99 protected: 100 /** 101 * Initializes the internal sub-widget pointers. 102 * Should be called after initializing the widget's grid. 103 */ 104 void finalize_setup(); 105 106 /** Inherited form @ref chat_handler */ 107 virtual void user_relation_changed(const std::string& name) override; 108 109 /** Inherited form @ref chat_handler */ 110 virtual void add_chat_message(const time_t& time, 111 const std::string& speaker, 112 int side, 113 const std::string& message, 114 events::chat_handler::MESSAGE_TYPE type 115 = events::chat_handler::MESSAGE_PRIVATE) override; 116 117 /** Inherited form @ref chat_handler */ 118 virtual void add_whisper_sent(const std::string& receiver, 119 const std::string& message) override; 120 121 /** Inherited form @ref chat_handler */ 122 virtual void add_whisper_received(const std::string& sender, 123 const std::string& message) override; 124 125 /** Inherited form @ref chat_handler */ 126 virtual void add_chat_room_message_sent(const std::string& room, 127 const std::string& message) override; 128 129 /** Inherited form @ref chat_handler */ 130 virtual void add_chat_room_message_received(const std::string& room, 131 const std::string& speaker, 132 const std::string& message) override; 133 134 private: 135 listbox* roomlistbox_; 136 137 multi_page* chat_log_container_; 138 139 text_box* chat_input_; 140 141 std::vector<lobby_chat_window> open_windows_; 142 143 size_t active_window_; 144 145 std::function<void(void)> active_window_changed_callback_; 146 147 mp::lobby_info* lobby_info_; 148 149 wesnothd_connection* wesnothd_connection_; 150 151 std::map<std::string, chatroom_log>* log_; 152 153 public: 154 /** Static type getter that does not rely on the widget being constructed. */ 155 static const std::string& type(); 156 157 private: 158 /** Inherited from styled_widget, implemented by REGISTER_WIDGET. */ 159 virtual const std::string& get_control_type() const override; 160 161 /** See @ref container_base::set_self_active. */ set_self_active(const bool)162 virtual void set_self_active(const bool /*active*/) override 163 { 164 /* DO NOTHING */ 165 } 166 167 void chat_input_keypress_callback(const SDL_Keycode key); 168 169 void append_to_chatbox(const std::string& text, const bool force_scroll = false); 170 171 void append_to_chatbox(const std::string& text, size_t id, const bool force_scroll = false); 172 173 /** @returns true if the whisper window for "name" is the active window. */ 174 bool whisper_window_active(const std::string& name); 175 176 /** @returns true if the room window for "room" is the active window. */ 177 bool room_window_active(const std::string& room); 178 179 /** Mark the whisper window for "name" as having one more pending message. */ 180 void increment_waiting_whispers(const std::string& name); 181 182 /** Mark the room window for "room" as having one more pending message. */ 183 void increment_waiting_messages(const std::string& room); 184 185 /** Add a whisper message to the whisper window. */ 186 void add_whisper_window_whisper(const std::string& sender, 187 const std::string& message); 188 189 /** 190 * Add a whisper message to the current window which is not the whisper window for "name". 191 */ 192 void add_active_window_whisper(const std::string& sender, 193 const std::string& message, 194 const bool force_scroll = false); 195 196 /** Add a message to the window for room "room". */ 197 void add_room_window_message(const std::string& room, 198 const std::string& sender, 199 const std::string& message); 200 201 /** Add a message to the window for room "room". */ 202 void add_active_window_message(const std::string& sender, 203 const std::string& message, 204 const bool force_scroll = false); 205 206 void close_window(size_t idx); 207 208 public: 209 /** Inherited form @ref chat_handler */ 210 virtual void send_chat_message(const std::string& message, bool allies_only) override; 211 212 /** 213 * Switch to the window given by a valid pointer (e.g. received from a call 214 * to *_window_open) 215 */ 216 void switch_to_window(lobby_chat_window* t); 217 218 void switch_to_window(size_t id); 219 220 void active_window_changed(); 221 222 /** 223 * Get the room* corresponding to the currently active window, or nullptr 224 * if a whisper window is active at the moment 225 */ 226 mp::room_info* active_window_room(); 227 228 /** 229 * Check if a room window for "room" is open, if open_new is true 230 * then it will be created if not found. If allow_close is false, the 231 * 'close' button will be disabled. 232 * @return valid ptr if the window was found or added, null otherwise 233 */ 234 lobby_chat_window* room_window_open(const std::string& room, 235 const bool open_new, const bool allow_close = true); 236 237 /** 238 * Check if a whisper window for user "name" is open, if open_new is true 239 * then it will be created if not found. 240 * @return valid ptr if the window was found or added, null otherwise 241 */ 242 lobby_chat_window* whisper_window_open(const std::string& name, bool open_new); 243 244 /** 245 * Helper function to find and open a new window, used by *_window_open 246 */ 247 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); 248 249 void close_window_button_callback(std::string room_name, bool& handled, bool& halt); 250 251 void process_room_join(const ::config& data); 252 253 void process_room_part(const ::config& data); 254 255 void process_room_query_response(const ::config& data); 256 257 void process_message(const ::config& data, bool whisper = false); 258 259 void process_network_data(const ::config& data); 260 261 private: 262 void signal_handler_receive_keyboard_focus(const event::ui_event event); 263 }; 264 265 // }---------- DEFINITION ---------{ 266 267 struct chatbox_definition : public styled_widget_definition 268 { 269 explicit chatbox_definition(const config& cfg); 270 271 struct resolution : public resolution_definition 272 { 273 explicit resolution(const config& cfg); 274 275 builder_grid_ptr grid; 276 }; 277 }; 278 279 // }---------- BUILDER -----------{ 280 281 namespace implementation 282 { 283 284 struct builder_chatbox : public builder_styled_widget 285 { 286 public: 287 explicit builder_chatbox(const config& cfg); 288 289 using builder_styled_widget::build; 290 291 widget* build() const; 292 293 private: 294 }; 295 296 } // namespace implementation 297 298 // }------------ END -------------- 299 300 } // namespace gui2 301