diff options
author | Philipp Sehmisch <tmw@crushnet.org> | 2007-02-27 16:39:17 +0000 |
---|---|---|
committer | Philipp Sehmisch <tmw@crushnet.org> | 2007-02-27 16:39:17 +0000 |
commit | 7a6e4d3c87ca4d7cc851af47fd9ebb616168f4c9 (patch) | |
tree | a880298777fcbb47a897e45ce6344ddbdf61b210 /src/gui | |
parent | ec72908d291fff37486a70d1624cfcece23b9bf7 (diff) | |
download | mana-client-7a6e4d3c87ca4d7cc851af47fd9ebb616168f4c9.tar.gz mana-client-7a6e4d3c87ca4d7cc851af47fd9ebb616168f4c9.tar.bz2 mana-client-7a6e4d3c87ca4d7cc851af47fd9ebb616168f4c9.tar.xz mana-client-7a6e4d3c87ca4d7cc851af47fd9ebb616168f4c9.zip |
Implementation of chat channels by Trapdoor.
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/button.cpp | 9 | ||||
-rw-r--r-- | src/gui/button.h | 7 | ||||
-rw-r--r-- | src/gui/chat.cpp | 185 | ||||
-rw-r--r-- | src/gui/chat.h | 54 | ||||
-rw-r--r-- | src/gui/tabbedcontainer.cpp | 36 | ||||
-rw-r--r-- | src/gui/tabbedcontainer.h | 10 |
6 files changed, 262 insertions, 39 deletions
diff --git a/src/gui/button.cpp b/src/gui/button.cpp index 0055c89a..e607b66a 100644 --- a/src/gui/button.cpp +++ b/src/gui/button.cpp @@ -38,8 +38,9 @@ ImageRect Button::button[4]; int Button::mInstances = 0; Button::Button(const std::string& caption, const std::string &actionEventId, - gcn::ActionListener *listener): - gcn::Button(caption) + gcn::ActionListener *listener): + gcn::Button(caption), + mIsLogged(false) { setBorderSize(0); @@ -100,7 +101,7 @@ Button::draw(gcn::Graphics *graphics) if (!isEnabled()) { mode = 3; } - else if (isPressed()) { + else if (isPressed() || mIsLogged) { mode = 2; } else if (mHasMouse) { @@ -130,7 +131,7 @@ Button::draw(gcn::Graphics *graphics) textX = getWidth() - 4; break; default: - throw GCN_EXCEPTION("Button::draw. Uknown alignment."); + throw GCN_EXCEPTION("Button::draw. Unknown alignment."); } graphics->setFont(getFont()); diff --git a/src/gui/button.h b/src/gui/button.h index 1c2ec41b..eb73e311 100644 --- a/src/gui/button.h +++ b/src/gui/button.h @@ -53,9 +53,16 @@ class Button : public gcn::Button { */ void draw(gcn::Graphics* graphics); + /** + * Enable/Disable highlighting + */ + void setLogged(bool enable) + { mIsLogged = enable; } + private: static ImageRect button[4]; /**< Button state graphics */ static int mInstances; /**< Number of button instances */ + bool mIsLogged; /**< Makes the button appear pressed all the time */ }; #endif diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index d992c6dd..eb6b7612 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -29,17 +29,22 @@ #include <guichan/key.hpp> #include "browserbox.h" +#include "../channelmanager.h" +#include "../channel.h" #include "chatinput.h" +#include "gccontainer.h" #include "scrollarea.h" +#include "tabbedcontainer.h" #include "windowcontainer.h" #include "../game.h" #include "../localplayer.h" #include "../net/chatserver/chatserver.h" - #include "../net/gameserver/player.h" +#include "../utils/dtor.h" + ChatWindow::ChatWindow(): Window(""), mTmpVisible(false) @@ -56,17 +61,34 @@ ChatWindow::ChatWindow(): mChatInput->setActionEventId("chatinput"); mChatInput->addActionListener(this); - mTextOutput = new BrowserBox(BrowserBox::AUTO_WRAP); - mTextOutput->setOpaque(false); - mTextOutput->disableLinksAndUserColors(); - mScrollArea = new ScrollArea(mTextOutput); - mScrollArea->setPosition( - mScrollArea->getBorderSize(), mScrollArea->getBorderSize()); - mScrollArea->setScrollPolicy( + BrowserBox *textOutput = new BrowserBox(BrowserBox::AUTO_WRAP); + textOutput->setOpaque(false); + textOutput->disableLinksAndUserColors(); + ScrollArea *scrollArea = new ScrollArea(textOutput); + scrollArea->setPosition( + scrollArea->getBorderSize(), scrollArea->getBorderSize()); + scrollArea->setScrollPolicy( gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_ALWAYS); - mScrollArea->setOpaque(false); + scrollArea->setOpaque(false); + + GCContainer *tab = new GCContainer(); + tab->setWidth(getWidth() - 2 * tab->getBorderSize()); + tab->setHeight(getHeight() - 2 * tab->getBorderSize()); + tab->setOpaque(false); + tab->add(scrollArea); + + mContainer = new TabbedContainer(); + mContainer->addTab(tab, "General"); + mContainer->setOpaque(false); + mChannelOutput["General"] = textOutput; + mChannelScroll["General"] = scrollArea; + + mTabs["General"] = tab; + + mTextOutput = textOutput; + mScrollArea = scrollArea; - add(mScrollArea); + add(mContainer); add(mChatInput); // Add key listener to chat input to be able to respond to up/down @@ -74,6 +96,11 @@ ChatWindow::ChatWindow(): mCurHist = mHistory.end(); } +ChatWindow::~ChatWindow() +{ + for_each(mTabs.begin(), mTabs.end(), make_dtor(mTabs)); +} + void ChatWindow::logic() { @@ -85,14 +112,17 @@ ChatWindow::logic() area.height - mChatInput->getHeight() - mChatInput->getBorderSize()); mChatInput->setWidth(area.width - 2 * mChatInput->getBorderSize()); + mContainer->setWidth(area.width - 2 * mContainer->getBorderSize()); + mContainer->setHeight(area.height - 2 * mContainer->getBorderSize() - + mChatInput->getHeight() - 5); mScrollArea->setWidth(area.width - 2 * mScrollArea->getBorderSize()); mScrollArea->setHeight(area.height - 2 * mScrollArea->getBorderSize() - - mChatInput->getHeight() - 5); + mChatInput->getHeight() - 26); mScrollArea->logic(); } void -ChatWindow::chatLog(std::string line, int own) +ChatWindow::chatLog(std::string line, int own, std::string channelName) { // Delete overhead from the end of the list while ((int)mChatlog.size() > mItemsKeep) { @@ -103,6 +133,9 @@ ChatWindow::chatLog(std::string line, int own) tmp.own = own; tmp.nick = ""; + mTextOutput = mChannelOutput[channelName]; + mScrollArea = mChannelScroll[channelName]; + // Fix the owner of welcome message. if (line.substr(0, 7) == "Welcome") { @@ -196,7 +229,7 @@ ChatWindow::action(const gcn::ActionEvent &event) mCurHist = mHistory.end(); // Send the message to the server - chatSend(player_node->getName(), message); + chatSend(player_node->getName(), message, mContainer->getActiveWidget()); // Clear the text from the chat input mChatInput->setText(""); @@ -241,7 +274,7 @@ ChatWindow::isFocused() } void -ChatWindow::chatSend(const std::string &nick, std::string msg) +ChatWindow::chatSend(const std::string &nick, std::string msg, std::string channelName) { /* Some messages are managed client side, while others * require server handling by proper packet. Probably @@ -249,7 +282,15 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) // Prepare ordinary message if (msg.substr(0, 1) != "/") { - Net::GameServer::Player::say(msg); + if(mContainer->getActiveWidget() == "General") + { + Net::GameServer::Player::say(msg); + } + else + { + short channelId = channelManager->findByName(channelName)->getId(); + Net::ChatServer::chat(channelId, msg); + } } else if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE) { @@ -258,11 +299,15 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) } else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP) { - chatLog("-- Help --", BY_SERVER); - chatLog("/help : Display this help.", BY_SERVER); - chatLog("/announce : Global announcement (GM only)", BY_SERVER); - chatLog("/where : Display map name", BY_SERVER); - chatLog("/who : Display number of online users", BY_SERVER); + chatLog("-- Help --", BY_SERVER, channelName); + chatLog("/help > Display this help.", BY_SERVER, channelName); + chatLog("/announce > Global announcement (GM only)", BY_SERVER, channelName); + chatLog("/where > Display map name", BY_SERVER, channelName); + chatLog("/who > Display number of online users", BY_SERVER, channelName); + chatLog("/list > Display all public channels", BY_SERVER, channelName); + chatLog("/register > Register a new channel", BY_SERVER, channelName); + chatLog("/join > Join an already registered channel", BY_SERVER, channelName); + chatLog("/quit > Leave a channel", BY_SERVER, channelName); } else if (msg.substr(0, IS_WHERE_LENGTH) == IS_WHERE) { @@ -275,9 +320,46 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) MessageOut outMsg(0x00c1); */ } + else if (msg.substr(0, IS_REGCHANNEL_LENGTH) == IS_REGCHANNEL) + { + std::string channel = msg.substr(IS_REGCHANNEL_LENGTH, msg.size()); + chatLog("Requesting to register channel", BY_SERVER); + Net::ChatServer::registerChannel(channel, "", "", false); + } + else if (msg.substr(0, IS_JOINCHANNEL_LENGTH) == IS_JOINCHANNEL) + { + //TODO: have passwords too + msg = msg.substr(IS_JOINCHANNEL_LENGTH, msg.size()); + chatLog("Requesting to join channel " + msg, BY_SERVER); + if(msg != "") + { + enterChannel(msg, "None"); + } + else + { + chatLog("No channel name given", BY_SERVER); + } + } + else if (msg.substr(0, IS_LISTCHANNELS_LENGTH) == IS_LISTCHANNELS) + { + Net::ChatServer::getChannelList(); + } + else if (msg.substr(0, IS_QUITCHANNEL_LENGTH) == IS_QUITCHANNEL) + { + Channel* channel; + channel = channelManager->findByName(channelName); + if(channel) + { + Net::ChatServer::quitChannel(channel->getId()); + } + else + { + chatLog("Unable to quit this channel", BY_SERVER); + } + } else { - chatLog("Unknown command", BY_SERVER); + chatLog("Unknown command", BY_SERVER, channelName); } } @@ -360,6 +442,67 @@ ChatWindow::const_msg(CHATSKILL act) } void +ChatWindow::addChannel(short channelId, std::string channelName) +{ + Channel* channel = new Channel(channelId); + channel->setName(channelName); + channelManager->addChannel(channel); +} + +void +ChatWindow::removeChannel(short channelId) +{ + Channel* channel = channelManager->findById(channelId); + if(channel) + { + mContainer->removeTab(channel->getName()); + mTabs.erase(channel->getName()); + mChannelOutput.erase(channel->getName()); + mChannelScroll.erase(channel->getName()); + channelManager->removeChannel(channel); + mTextOutput = mChannelOutput["General"]; + mScrollArea = mChannelScroll["General"]; + } +} + +void +ChatWindow::createNewChannelTab(std::string channelName) +{ + BrowserBox *textOutput = new BrowserBox(BrowserBox::AUTO_WRAP); + textOutput->setOpaque(false); + textOutput->disableLinksAndUserColors(); + ScrollArea *scrollArea = new ScrollArea(textOutput); + scrollArea->setPosition(scrollArea->getBorderSize(), scrollArea->getBorderSize()); + scrollArea->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_ALWAYS); + scrollArea->setOpaque(false); + GCContainer *tab = new GCContainer(); + tab->setWidth(getWidth() - 2 * tab->getBorderSize()); + tab->setHeight(getHeight() - 2 * tab->getBorderSize()); + tab->add(scrollArea); + tab->setOpaque(false); + mContainer->addTab(tab, channelName); + mTabs[channelName] = tab; + mChannelOutput[channelName] = textOutput; + mChannelScroll[channelName] = scrollArea; + mScrollArea = scrollArea; + mTextOutput = textOutput; + logic(); +} + +void +ChatWindow::enterChannel(std::string channel, std::string password) +{ + Net::ChatServer::enterChannel(channel, password); +} + +void +ChatWindow::sendToChannel(short channelId, std::string user, std::string msg) +{ + std::string channelName = channelManager->findById(channelId)->getName(); + chatLog(user + ": " + msg, user == player_node->getName() ? BY_PLAYER : BY_OTHER, channelName); +} + +void ChatWindow::keyPressed(gcn::KeyEvent &event) { if (event.getKey().getValue() == gcn::Key::DOWN && diff --git a/src/gui/chat.h b/src/gui/chat.h index 963e5e98..c7e51ebf 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -26,6 +26,7 @@ #include <list> #include <string> +#include <map> #include <guichan/actionlistener.hpp> #include <guichan/keylistener.hpp> @@ -36,6 +37,8 @@ class BrowserBox; class ScrollArea; +class TabbedContainer; +class GCContainer; #define BY_GM 0 // those should be self-explanatory =) #define BY_PLAYER 1 @@ -53,6 +56,14 @@ class ScrollArea; #define IS_WHERE_LENGTH 6 #define IS_WHO "/who" #define IS_WHO_LENGTH 4 +#define IS_JOINCHANNEL "/join " +#define IS_JOINCHANNEL_LENGTH 6 +#define IS_REGCHANNEL "/register " +#define IS_REGCHANNEL_LENGTH 10 +#define IS_LISTCHANNELS "/list" +#define IS_LISTCHANNELS_LENGTH 5 +#define IS_QUITCHANNEL "/quit" +#define IS_QUITCHANNEL_LENGTH 5 /** * gets in between usernick and message text depending on @@ -118,6 +129,11 @@ class ChatWindow : public Window, public gcn::ActionListener, ChatWindow(); /** + * + */ + ~ChatWindow(); + + /** * Logic (updates components' size) */ void logic(); @@ -128,7 +144,7 @@ class ChatWindow : public Window, public gcn::ActionListener, * @param line Text message. * @parem own Type of message (usually the owner-type). */ - void chatLog(std::string line, int own); + void chatLog(std::string line, int own, std::string channelName = "General"); /* * Calls original chat_log() after processing the packet. @@ -175,7 +191,27 @@ class ChatWindow : public Window, public gcn::ActionListener, * chatlog.chat_send("Zaeiru", "Hello to all users on the screen!"); */ void - chatSend(const std::string &nick, std::string msg); + chatSend(const std::string &nick, std::string msg, std::string channelName); + + /** Called to add the channel to the channel manager */ + void + addChannel(short channel, std::string channelName); + + /** Called to remove the channel from the channel manager */ + void + removeChannel(short channel); + + /** Called to create a new channel tab */ + void + createNewChannelTab(std::string channelName); + + /** Called to join channel */ + void + enterChannel(std::string channel, std::string password = "None"); + + /** Called to output text to a specific channel */ + void + sendToChannel(short channel, std::string user, std::string msg); /** Called when key is pressed */ void @@ -192,7 +228,9 @@ class ChatWindow : public Window, public gcn::ActionListener, private: bool mTmpVisible; - /** One item in the chat log */ + int mItems; + int mItemsKeep; + typedef struct CHATLOG { std::string nick; @@ -200,15 +238,17 @@ class ChatWindow : public Window, public gcn::ActionListener, int own; }; - std::list<CHATLOG> mChatlog; /**< Chat log */ - - int mItems; - int mItemsKeep; + std::list<CHATLOG> mChatlog; /** Constructs failed messages for actions */ std::string const_msg(CHATSKILL); + std::map<std::string, GCContainer*> mTabs; + TabbedContainer *mContainer; /**< Tabbed container for tabbing between channels */ + GCContainer *mTab; /**< Tabs */ gcn::TextField *mChatInput; /**< Input box for typing chat messages */ + std::map<std::string, BrowserBox*> mChannelOutput; /**< Map each TextOutput to a tab */ + std::map<std::string, ScrollArea*> mChannelScroll; /**< Map each ScrollArea to a tab */ BrowserBox *mTextOutput; /**< Text box for displaying chat history */ ScrollArea *mScrollArea; /**< Scroll area around text output */ diff --git a/src/gui/tabbedcontainer.cpp b/src/gui/tabbedcontainer.cpp index 75f9f3cf..5d6d21d1 100644 --- a/src/gui/tabbedcontainer.cpp +++ b/src/gui/tabbedcontainer.cpp @@ -26,6 +26,7 @@ #include "button.h" #include "../utils/tostring.h" +#include "../utils/dtor.h" #define TABWIDTH 60 #define TABHEIGHT 20 @@ -37,10 +38,7 @@ TabbedContainer::TabbedContainer(): TabbedContainer::~TabbedContainer() { - for (WidgetIterator i = mTabs.begin(); i != mTabs.end(); i++) { - remove(*i); - delete (*i); - } + for_each(mTabs.begin(), mTabs.end(), make_dtor(mTabs)); mTabs.clear(); mContents.clear(); @@ -55,7 +53,7 @@ void TabbedContainer::addTab(gcn::Widget *widget, const std::string &caption) tab->setSize(TABWIDTH, TABHEIGHT); add(tab, TABWIDTH * tabNumber, 0); - mTabs.push_back(tab); + mTabs[caption] = tab; mContents.push_back(widget); widget->setPosition(0, TABHEIGHT); @@ -64,7 +62,18 @@ void TabbedContainer::addTab(gcn::Widget *widget, const std::string &caption) if (!mActiveContent) { mActiveContent = widget; add(mActiveContent); + tab->setLogged(true); } + + mWidgets[widget] = caption; +} + +void TabbedContainer::removeTab(const std::string &caption) +{ + gcn::ActionEvent actionEvent(this, "0"); + action(actionEvent); + remove(mTabs[caption]); + mTabs.erase(caption); } void TabbedContainer::logic() @@ -80,16 +89,21 @@ void TabbedContainer::logic() void TabbedContainer::action(const gcn::ActionEvent &event) { - std::stringstream ss(event.getId()); int tabNo; + std::stringstream ss(event.getId()); ss >> tabNo; gcn::Widget *newContent = mContents[tabNo]; + if (newContent) { if (mActiveContent) { + // Unhighlight old tab + ((Button*)mTabs[mWidgets[mActiveContent]])->setLogged(false); remove(mActiveContent); } mActiveContent = newContent; + // Highlight new tab + ((Button*)mTabs[mWidgets[mActiveContent]])->setLogged(true); add(newContent); } } @@ -98,3 +112,13 @@ void TabbedContainer::setOpaque(bool opaque) { Container::setOpaque(opaque); } + +short TabbedContainer::getNumberOfTabs() +{ + return mTabs.size(); +} + +std::string TabbedContainer::getActiveWidget() +{ + return mWidgets[mActiveContent]; +} diff --git a/src/gui/tabbedcontainer.h b/src/gui/tabbedcontainer.h index 2dc017ae..7f8deef9 100644 --- a/src/gui/tabbedcontainer.h +++ b/src/gui/tabbedcontainer.h @@ -26,6 +26,7 @@ #include <iosfwd> #include <vector> +#include <map> #include <guichan/actionlistener.hpp> @@ -41,18 +42,25 @@ class TabbedContainer : public gcn::Container, public gcn::ActionListener void addTab(gcn::Widget *widget, const std::string &caption); + void removeTab(const std::string &caption); + void logic(); void action(const gcn::ActionEvent &event); void setOpaque(bool opaque); + short getNumberOfTabs(); + + std::string getActiveWidget(); + private: typedef std::vector<gcn::Widget*> Widgets; typedef Widgets::iterator WidgetIterator; - Widgets mTabs; // The actual tabs at the top + std::map<std::string, gcn::Widget*> mTabs; // tabs mapped to their channel name Widgets mContents; // The contents of the tabs + std::map<gcn::Widget*, std::string> mWidgets; gcn::Widget *mActiveContent; }; |