Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007 #include "SimpleChatWidget.h"
00008 #include "SimpleChatServer.h"
00009
00010 #include <Wt/WApplication>
00011 #include <Wt/WContainerWidget>
00012 #include <Wt/WEnvironment>
00013 #include <Wt/WHBoxLayout>
00014 #include <Wt/WVBoxLayout>
00015 #include <Wt/WLabel>
00016 #include <Wt/WLineEdit>
00017 #include <Wt/WText>
00018 #include <Wt/WTextArea>
00019 #include <Wt/WPushButton>
00020 #include <Wt/WCheckBox>
00021
00022 #include <iostream>
00023
00024 using namespace Wt;
00025
00026 SimpleChatWidget::SimpleChatWidget(SimpleChatServer& server,
00027 Wt::WContainerWidget *parent)
00028 : WContainerWidget(parent),
00029 server_(server),
00030 app_(WApplication::instance()),
00031 messageReceived_("sounds/message_received.mp3")
00032 {
00033 user_ = server_.suggestGuest();
00034 letLogin();
00035
00036
00037
00038
00039 app_->enableUpdates();
00040 }
00041
00042 SimpleChatWidget::~SimpleChatWidget()
00043 {
00044 logout();
00045 }
00046
00047 void SimpleChatWidget::letLogin()
00048 {
00049 clear();
00050
00051 WVBoxLayout *vLayout = new WVBoxLayout();
00052 setLayout(vLayout, AlignLeft | AlignTop);
00053
00054 WHBoxLayout *hLayout = new WHBoxLayout();
00055 vLayout->addLayout(hLayout);
00056
00057 hLayout->addWidget(new WLabel("User name:"), 0, AlignMiddle);
00058 hLayout->addWidget(userNameEdit_ = new WLineEdit(user_), 0, AlignMiddle);
00059 userNameEdit_->setFocus();
00060
00061 WPushButton *b = new WPushButton("Login");
00062 hLayout->addWidget(b, 0, AlignMiddle);
00063 hLayout->addStretch(1);
00064
00065 b->clicked().connect(SLOT(this, SimpleChatWidget::login));
00066 userNameEdit_->enterPressed().connect(SLOT(this, SimpleChatWidget::login));
00067
00068 vLayout->addWidget(statusMsg_ = new WText());
00069 statusMsg_->setTextFormat(PlainText);
00070 }
00071
00072 void SimpleChatWidget::login()
00073 {
00074 WString name = WWebWidget::escapeText(userNameEdit_->text());
00075
00076 if (!startChat(name))
00077 statusMsg_->setText("Sorry, name '" + name + "' is already taken.");
00078 }
00079
00080 void SimpleChatWidget::logout()
00081 {
00082 if (eventConnection_.connected()) {
00083 eventConnection_.disconnect();
00084 server_.logout(user_);
00085
00086 letLogin();
00087 }
00088 }
00089
00090 bool SimpleChatWidget::startChat(const WString& user)
00091 {
00092 if (server_.login(user)) {
00093 eventConnection_
00094 = server_.chatEvent().connect(SLOT(this,
00095 SimpleChatWidget::processChatEvent));
00096 user_ = user;
00097
00098 clear();
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 WVBoxLayout *vLayout = new WVBoxLayout();
00119
00120
00121 WHBoxLayout *hLayout = new WHBoxLayout();
00122
00123
00124 hLayout->addWidget(messages_ = new WContainerWidget(), 1);
00125 messages_->setStyleClass("chat-msgs");
00126
00127 messages_->setOverflow(WContainerWidget::OverflowAuto);
00128
00129
00130 hLayout->addWidget(userList_ = new WContainerWidget());
00131 userList_->setStyleClass("chat-users");
00132 userList_->setOverflow(WContainerWidget::OverflowAuto);
00133
00134 hLayout->setResizable(0, true);
00135
00136
00137 vLayout->addLayout(hLayout, 1);
00138
00139
00140 vLayout->addWidget(messageEdit_ = new WTextArea());
00141 messageEdit_->setStyleClass("chat-noedit");
00142 messageEdit_->setRows(2);
00143 messageEdit_->setFocus();
00144
00145
00146 hLayout = new WHBoxLayout();
00147
00148
00149 hLayout->addWidget(sendButton_ = new WPushButton("Send"));
00150 WPushButton *b;
00151
00152
00153 hLayout->addWidget(b = new WPushButton("Logout"));
00154
00155
00156 hLayout->addStretch(1);
00157
00158
00159 vLayout->addLayout(hLayout);
00160
00161 setLayout(vLayout);
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 clearInput_.setJavaScript
00176 ("function(o, e) {"
00177 "" + messageEdit_->jsRef() + ".value='';"
00178 "}");
00179
00180
00181 sendButton_->clicked().connect(SLOT(this, SimpleChatWidget::send));
00182 messageEdit_->enterPressed().connect(SLOT(this, SimpleChatWidget::send));
00183 sendButton_->clicked().connect(clearInput_);
00184 messageEdit_->enterPressed().connect(clearInput_);
00185
00186
00187
00188 messageEdit_->enterPressed().setPreventDefault(true);
00189
00190 b->clicked().connect(SLOT(this, SimpleChatWidget::logout));
00191
00192 WText *msg = new WText
00193 ("<div><span class='chat-info'>You are joining the conversation as "
00194 + user_ + "</span></div>", messages_);
00195 msg->setStyleClass("chat-msg");
00196
00197 updateUsers();
00198
00199 return true;
00200 } else
00201 return false;
00202 }
00203
00204 void SimpleChatWidget::send()
00205 {
00206 if (!messageEdit_->text().empty()) {
00207 server_.sendMessage(user_, messageEdit_->text());
00208 if (!WApplication::instance()->environment().ajax())
00209 messageEdit_->setText(WString::Empty);
00210 }
00211
00212 messageEdit_->setFocus();
00213 }
00214
00215 void SimpleChatWidget::updateUsers()
00216 {
00217 userList_->clear();
00218
00219 SimpleChatServer::UserSet users = server_.users();
00220
00221 UserMap oldUsers = users_;
00222 users_.clear();
00223
00224 for (SimpleChatServer::UserSet::iterator i = users.begin();
00225 i != users.end(); ++i) {
00226 WCheckBox *w = new WCheckBox(*i, userList_);
00227 w->setInline(false);
00228
00229 UserMap::const_iterator j = oldUsers.find(*i);
00230 if (j != oldUsers.end())
00231 w->setChecked(j->second);
00232 else
00233 w->setChecked(true);
00234
00235 users_[*i] = w->isChecked();
00236 w->changed().connect(SLOT(this, SimpleChatWidget::updateUser));
00237
00238 if (*i == user_)
00239 w->setStyleClass("chat-self");
00240 }
00241 }
00242
00243 void SimpleChatWidget::updateUser()
00244 {
00245 WCheckBox *b = dynamic_cast<WCheckBox *>(sender());
00246 users_[b->text()] = b->isChecked();
00247 }
00248
00249 void SimpleChatWidget::processChatEvent(const ChatEvent& event)
00250 {
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 WApplication::UpdateLock lock = app_->getUpdateLock();
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 bool needPush = false;
00272
00273
00274
00275
00276 if (event.type() != ChatEvent::Message) {
00277 needPush = true;
00278 updateUsers();
00279 }
00280
00281 bool display = event.type() != ChatEvent::Message
00282 || (users_.find(event.user()) != users_.end() && users_[event.user()]);
00283
00284 if (display) {
00285 needPush = true;
00286
00287 WText *w = new WText(event.formattedHTML(user_), messages_);
00288 w->setInline(false);
00289 w->setStyleClass("chat-msg");
00290
00291
00292
00293
00294 if (messages_->count() > 100)
00295 delete messages_->children()[0];
00296
00297
00298
00299
00300 app_->doJavaScript(messages_->jsRef() + ".scrollTop += "
00301 + messages_->jsRef() + ".scrollHeight;");
00302
00303
00304 if (event.user() != user_)
00305 messageReceived_.play();
00306 }
00307
00308 if (needPush)
00309 app_->triggerUpdate();
00310 }