/* 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(); // window title chat_titlelabel = new ui::Label(this); chat_titlelabel->set_label("title"); chat_titlelabel->set_background(false); chat_titlelabel->set_border(false); chat_titlelabel->set_font(ui::root()->font_large()); chat_titlelabel->set_alignment(ui::AlignCenter); chat_titlelabel->set_text("CHAT"); // close button chat_closebutton = new ui::IconButton(chat_titlelabel, "bitmaps/icons/window_close"); // player list chat_playerlist = new ui::ListView(this); chat_playerlist->set_label("playerlist"); // ---- right pane chat_pane_right = new ui::Widget(this); chat_pane_right->set_background(true); chat_pane_right->set_border(true); chat_pane_right->set_focus(); // chat text chat_scrollpane = new ui::ScrollPane(chat_pane_right, chat_log); chat_scrollpane->set_background(false); chat_scrollpane->set_border(false); chat_scrollpane->set_label("text"); // chat input chat_input = new ui::InputBox(chat_pane_right); chat_input->set_background(false); chat_input->set_border(false); set_prompt(); 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); } bool Chat::on_emit(ui::Widget *sender, const ui::Widget::Event event, void *data) { if (sender == chat_closebutton) { if (event == ui::Widget::EventButtonClicked) { hide(); return true; } } return Window::on_emit(sender, event, data); } 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; client()->say(chat_input->text()); } (*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_TAB: if (chat_input->text().size() && chat_input->text()[0] == '/') { // command mode chat_input->complete(); } else { // TODO chat mode, switch channel } 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::set_prompt() { if (chat_input->text().size() && chat_input->text()[0] == '/') { chat_input->set_prompt("^BCommand^F:^B "); } else { chat_input->set_prompt("^BSay^F:^B "); } } void Chat::draw() { if (!chat_small && (chat_playerlist_timestamp != core::game()->playerlist_timestamp())) { refresh(); } set_prompt(); ui::Window::draw(); } void Chat::refresh() { chat_playerlist->clear(); ui::ListItem *listitem = 0; /* listitem = new ui::ListItem(chat_playerlist, "Shout"); listitem->set_height(listitem->font()->height() * 2.0f); listitem->set_sortkey(" 0"); listitem = new ui::ListItem(chat_playerlist, "Say"); listitem->set_height(listitem->font()->height() * 2.0f); listitem->set_sortkey(" 1"); */ for (core::GameInterface::Players::const_iterator it = core::game()->players().begin(); it != core::game()->players().end(); it++) { std::string descr(aux::text_strip((*it)->name().c_str())); if ((*it)->zone()) { descr.append("\n^N"); descr.append(aux::pad_left((*it)->zone()->name(), 20)); } listitem = new ui::ListItem(chat_playerlist, descr.c_str()); listitem->set_height(listitem->font()->height() * 3.0f); listitem->set_sortkey(aux::text_strip_lowercase((*it)->name())); } chat_playerlist->sort(); chat_playerlist_timestamp = core::game()->playerlist_timestamp(); } void Chat::resize() { const float padding = ui::root()->font_large()->height(); if (chat_small) { chat_titlelabel->hide(); chat_playerlist->hide(); chat_scrollpane->hide(); // resize right panbe to input bar size chat_pane_right->set_size(size()); chat_pane_right->set_location(0.0f, 0.0f); // input bar chat_input->set_size(chat_pane_right->width() - 2.0f * padding, chat_input->font()->height()); chat_input->set_location(padding, (chat_pane_right->height() - chat_input->height()) * 0.5f ); } else { chat_titlelabel->show(); chat_playerlist->show(); chat_scrollpane->show(); // resize title label chat_titlelabel->set_size(width() - padding * 2.0f, chat_titlelabel->font()->height()); chat_titlelabel->set_location(padding, padding); // resize close button chat_closebutton->set_size(chat_titlelabel->font()->height(), chat_titlelabel->font()->height()); chat_closebutton->set_location(chat_titlelabel->width() - chat_closebutton->width(), 0); // resize player names listview chat_playerlist->set_location(padding, chat_titlelabel->bottom() + padding); chat_playerlist->set_size(ui::UI::elementsize.width(), height() - chat_titlelabel->bottom() - padding * 2.0f); // resize right pane chat_pane_right->set_size(width() - chat_playerlist->right() - padding * 2.0f, chat_playerlist->height()); chat_pane_right->set_location(chat_playerlist->right() + padding, chat_titlelabel->bottom() + padding); { const ui::Widget *pane = chat_pane_right; const float margin_horizontal = pane->font()->width(); const float margin_vertical = pane->font()->height() * 0.5f; // resize input bar chat_input->set_size(pane->width() - 2.0f * margin_horizontal, chat_input->font()->height()); chat_input->set_location(margin_horizontal, pane->height() - chat_input->height() - margin_vertical); // resize chat text pane chat_scrollpane->set_size(pane->width() - 2.0f * margin_horizontal, chat_input->top() - 2.0f * margin_vertical); chat_scrollpane->set_location(margin_horizontal, margin_vertical); } } } } // namespace client