/* client/chat.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include "auxiliary/functions.h" #include "client/chat.h" #include "client/client.h" #include "core/core.h" #include "core/gameinterface.h" #include "sys/sys.h" #include "ui/ui.h" namespace client { const size_t DEFAULT_CHAT_LOG_SIZE = 2048; const size_t DEFAULT_CHAT_HISTO_SIZE = 512; Chat::Chat(ui::Widget *parent) : ui::Window(parent) { set_label("chat"); history.clear(); history.push_back(""); history_pos = history.rbegin(); chat_scrollpane = new ui::ScrollPane(this, chat_log); chat_scrollpane->set_border(false); chat_scrollpane->set_label("text"); chat_playerlist = new ui::ListView(this); chat_playerlist->set_label("playerlist"); chat_input = new ui::InputBox(this); chat_input->set_border(false); chat_input->set_prompt("^BSay^F:^B "); chat_input->set_focus(); set_background(true); set_visible(false); chat_small = false; chat_playerlist_timestamp = 0; } Chat::~Chat() { history.clear(); } void Chat::clear() { chat_log.clear(); chat_input->clear(); chat_playerlist->clear(); chat_playerlist_timestamp = 0; } void Chat::set_small_view(bool small_chat_view) { chat_small = small_chat_view; resize(); } void Chat::event_text(const std::string & text) { while (chat_log.size() >= DEFAULT_CHAT_LOG_SIZE) { chat_log.pop_front(); } chat_log.push_back(text); } void Chat::show() { Window::show(); history_pos = history.rbegin(); (*history_pos).clear(); chat_input->set_text((*history_pos)); chat_scrollpane->set_scroll(0); } void Chat::toggle() { if (visible()) hide(); else show(); } bool Chat::on_keypress(const int key, const unsigned int modifier) { // number of lines to scroll const size_t scroll_offset = 3; History::reverse_iterator upit; switch (key) { case SDLK_ESCAPE: if (visible()) { hide(); return true; } else { return false; } case SDLK_RETURN: if (chat_input->text().size()) { // store input into history while (history.size() >= DEFAULT_CHAT_HISTO_SIZE) { history.pop_front(); } if (chat_input->text().c_str()[0] == '/' || chat_input->text().c_str()[0] == '\\') { core::cmd() << &chat_input->text().c_str()[1] << std::endl; } else { // FIXME semi-column ; truncates the command core::cmd() << "say " << chat_input->text() << std::endl; } (*history.rbegin()) = chat_input->text(); history.push_back(""); history_pos = history.rbegin(); chat_input->set_text((*history_pos)); if (chat_small) hide(); } else { hide(); } return true; break; case SDLK_UP: upit = history_pos; ++upit; if (upit != history.rend()) { history_pos = upit; chat_input->set_text((*history_pos)); } return true; break; case SDLK_DOWN: if (history_pos != history.rbegin()) { --history_pos; chat_input->set_text((*history_pos)); } return true; break; case SDLK_PAGEUP: chat_scrollpane->inc_scroll(scroll_offset); return true; break; case SDLK_PAGEDOWN: chat_scrollpane->dec_scroll(scroll_offset); return true; break; } return false; } void Chat::draw() { if (!chat_small && (chat_playerlist_timestamp != core::game()->playerlist_timestamp())) { update_player_list(); } ui::Window::draw(); } void Chat::update_player_list() { chat_playerlist->clear(); for (core::GameInterface::Players::const_iterator it = core::game()->players().begin(); it != core::game()->players().end(); it++) { ui::ListItem *listitem = new ui::ListItem(chat_playerlist, (*it)->name().c_str()); listitem->set_height(listitem->font()->height() * 1.5f); listitem->set_sortkey(aux::text_strip_lowercase((*it)->name())); } chat_playerlist->sort(); chat_playerlist_timestamp = core::game()->playerlist_timestamp(); } void Chat::resize() { const float fontmargin = ui::root()->font_large()->height(); if (chat_small) { chat_playerlist->hide(); chat_scrollpane->hide(); } else { chat_playerlist->show(); chat_scrollpane->show(); // player names chat_playerlist->set_size(ui::UI::elementsize.width(), height() - fontmargin * 3.0f); chat_playerlist->set_location(width() - ui::UI::elementsize.width() - fontmargin, fontmargin); // chat text chat_scrollpane->set_size(width() - ui::UI::elementsize.width() - fontmargin * 3.0f, height() - fontmargin * 3.0f); chat_scrollpane->set_location(fontmargin, fontmargin); } // input bar chat_input->set_location(fontmargin, height() - fontmargin); chat_input->set_size(width() - 2.0f * fontmargin , fontmargin); } } // namespace client