00001
00002
00003
00004
00005
00006
00007 #include "SimpleChatWidget.h"
00008 #include "SimpleChatServer.h"
00009
00010 #include <WApplication>
00011 #include <WContainerWidget>
00012 #include <WLineEdit>
00013 #include <WTable>
00014 #include <WTableCell>
00015 #include <WText>
00016 #include <WTextArea>
00017 #include <WPushButton>
00018
00019 #include <iostream>
00020
00021 using namespace Wt;
00022
00023 SimpleChatWidget::SimpleChatWidget(SimpleChatServer& server,
00024 Wt::WContainerWidget *parent)
00025 : WCompositeWidget(parent),
00026 server_(server),
00027 app_(WApplication::instance())
00028 {
00029 setImplementation(layout_ = new WContainerWidget());
00030
00031 setPositionScheme(Relative);
00032
00033 user_ = server_.suggestGuest();
00034 letLogin();
00035
00036 app_->enableUpdates();
00037 }
00038
00039 SimpleChatWidget::~SimpleChatWidget()
00040 {
00041 logout();
00042 }
00043
00044 void SimpleChatWidget::letLogin()
00045 {
00046 layout_->clear();
00047
00048 new WText("User name: ", layout_);
00049 userNameEdit_ = new WLineEdit(user_, layout_);
00050 userNameEdit_->setFocus();
00051
00052 WPushButton *b = new WPushButton("Login", layout_);
00053 b->setMargin(5, WWidget::Left);
00054
00055 b->clicked.connect(SLOT(this, SimpleChatWidget::login));
00056 userNameEdit_->enterPressed.connect(SLOT(this, SimpleChatWidget::login));
00057
00058 statusMsg_ = new WText(layout_);
00059 statusMsg_->setFormatting(WText::PlainFormatting);
00060 statusMsg_->setInline(false);
00061 }
00062
00063 void SimpleChatWidget::login()
00064 {
00065 WString name = WWebWidget::escapeText(userNameEdit_->text());
00066
00067 if (!startChat(name))
00068 statusMsg_->setText("Sorry, name '" + name + "' is already taken.");
00069 }
00070
00071 void SimpleChatWidget::logout()
00072 {
00073 if (eventConnection_.connected()) {
00074 server_.logout(user_);
00075 eventConnection_.disconnect();
00076
00077 messageEditArea_->clear();
00078
00079 WPushButton *b = new WPushButton("Login again", messageEditArea_);
00080 b->clicked.connect(SLOT(this, SimpleChatWidget::letLogin));
00081 }
00082 }
00083
00084 bool SimpleChatWidget::startChat(const WString& user)
00085 {
00086 if (server_.login(user)) {
00087 eventConnection_
00088 = server_.chatEvent.connect(SLOT(this,
00089 SimpleChatWidget::processChatEvent));
00090 user_ = user;
00091
00092 static const int MESSAGE_EDIT_AREA_HEIGHT = 80;
00093 static const int USERS_WIDTH_PERCENTAGE = 15;
00094
00095 layout_->clear();
00096
00097 messages_ = new WContainerWidget(layout_);
00098 messages_->setStyleClass("chat-msgs");
00099 messages_->setPositionScheme(Absolute);
00100 messages_->setOffsets(0, Left | Top);
00101 messages_
00102 ->resize(WLength(100 - USERS_WIDTH_PERCENTAGE - 1, WLength::Percentage),
00103 height().value() - MESSAGE_EDIT_AREA_HEIGHT - 3);
00104 messages_->setOverflow(WContainerWidget::OverflowAuto, Vertical);
00105
00106 messageEditArea_ = new WContainerWidget(layout_);
00107 messageEditArea_->setPositionScheme(Absolute);
00108 messageEditArea_->setOffsets(0, Left | Bottom);
00109 messageEditArea_->resize(WLength(100, WLength::Percentage),
00110 MESSAGE_EDIT_AREA_HEIGHT);
00111
00112 WContainerWidget *a = new WContainerWidget(messageEditArea_);
00113 a->setContentAlignment(AlignCenter);
00114
00115 messageEdit_ = new WTextArea(a);
00116 messageEdit_->setStyleClass("chat-noedit");
00117 messageEdit_->setRows(2);
00118 messageEdit_->resize(WLength(99, WLength::Percentage), WLength());
00119 messageEdit_->setFocus();
00120
00121 sendButton_ = new WPushButton("Send", messageEditArea_);
00122
00123 sendButton_->clicked.connect(SLOT(sendButton_, WPushButton::disable));
00124 sendButton_->clicked.connect(SLOT(messageEdit_, WTextArea::disable));
00125 sendButton_->clicked.connect(SLOT(this, SimpleChatWidget::send));
00126
00127 messageEdit_->enterPressed.connect(SLOT(sendButton_, WPushButton::disable));
00128 messageEdit_->enterPressed.connect(SLOT(messageEdit_, WTextArea::disable));
00129 messageEdit_->enterPressed.connect(SLOT(this, SimpleChatWidget::send));
00130
00131 WPushButton *b = new WPushButton("Logout", messageEditArea_);
00132 b->clicked.connect(SLOT(this, SimpleChatWidget::logout));
00133
00134 userList_ = new WContainerWidget(layout_);
00135 userList_->setStyleClass("chat-users");
00136 userList_->setPositionScheme(Absolute);
00137 userList_->setOffsets(0, Top | Right);
00138 userList_->resize(WLength(USERS_WIDTH_PERCENTAGE, WLength::Percentage),
00139 height().value() - MESSAGE_EDIT_AREA_HEIGHT - 3);
00140
00141 WText *w
00142 = new WText(false,
00143 "<span class='chat-info'>You are joining the conversation as "
00144 + user_ + "</span>", messages_);
00145 w->setStyleClass("chat-msg");
00146
00147 updateUsers();
00148
00149 return true;
00150 } else
00151 return false;
00152 }
00153
00154 void SimpleChatWidget::send()
00155 {
00156 if (!messageEdit_->text().empty()) {
00157 server_.sendMessage(user_, messageEdit_->text());
00158 messageEdit_->setText("");
00159 }
00160
00161 messageEdit_->enable();
00162 messageEdit_->setFocus();
00163 sendButton_->enable();
00164 }
00165
00166 void SimpleChatWidget::updateUsers()
00167 {
00168 userList_->clear();
00169
00170 SimpleChatServer::UserSet users = server_.users();
00171
00172 WString usersStr;
00173
00174 for (SimpleChatServer::UserSet::iterator i = users.begin();
00175 i != users.end(); ++i) {
00176 if (*i == user_)
00177 usersStr += "<span class='chat-self'>" + *i + "</span><br />";
00178 else
00179 usersStr += *i + "<br />";
00180 }
00181
00182 userList_->addWidget(new WText(false, usersStr));
00183 }
00184
00185 void SimpleChatWidget::processChatEvent(const ChatEvent& event)
00186 {
00187
00188
00189
00190
00191
00192
00193
00194
00195 WApplication::UpdateLock lock = app_->getUpdateLock();
00196
00197 WText *w = new WText(false, event.formattedHTML(user_), messages_);
00198 w->setStyleClass("chat-msg");
00199
00200
00201 if (messages_->count() > 100)
00202 delete messages_->children()[0];
00203
00204 if (event.type() != ChatEvent::Message)
00205 updateUsers();
00206
00207
00208
00209
00210 app_->doJavaScript(messages_->jsRef() + ".scrollTop += "
00211 + messages_->jsRef() + ".scrollHeight;");
00212
00213
00214
00215
00216 app_->triggerUpdate();
00217 }