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 SimpleChatWidget::~SimpleChatWidget()
00038 {
00039 logout();
00040 }
00041
00042 void SimpleChatWidget::letLogin()
00043 {
00044 clear();
00045
00046 WVBoxLayout *vLayout = new WVBoxLayout();
00047 setLayout(vLayout, AlignLeft | AlignTop);
00048
00049 WHBoxLayout *hLayout = new WHBoxLayout();
00050 vLayout->addLayout(hLayout);
00051
00052 hLayout->addWidget(new WLabel("User name:"), 0, AlignMiddle);
00053 hLayout->addWidget(userNameEdit_ = new WLineEdit(user_), 0, AlignMiddle);
00054 userNameEdit_->setFocus();
00055
00056 WPushButton *b = new WPushButton("Login");
00057 hLayout->addWidget(b, 0, AlignMiddle);
00058 hLayout->addStretch(1);
00059
00060 b->clicked().connect(this, &SimpleChatWidget::login);
00061 userNameEdit_->enterPressed().connect(this, &SimpleChatWidget::login);
00062
00063 vLayout->addWidget(statusMsg_ = new WText());
00064 statusMsg_->setTextFormat(PlainText);
00065 }
00066
00067 void SimpleChatWidget::login()
00068 {
00069 WString name = WWebWidget::escapeText(userNameEdit_->text());
00070
00071 if (!startChat(name))
00072 statusMsg_->setText("Sorry, name '" + name + "' is already taken.");
00073 }
00074
00075 void SimpleChatWidget::logout()
00076 {
00077 if (eventConnection_.connected()) {
00078 eventConnection_.disconnect();
00079 server_.logout(user_);
00080
00081 app_->enableUpdates(false);
00082
00083 letLogin();
00084 }
00085 }
00086
00087 void SimpleChatWidget::createLayout(WWidget *messages, WWidget *userList,
00088 WWidget *messageEdit,
00089 WWidget *sendButton, WWidget *logoutButton)
00090 {
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 WVBoxLayout *vLayout = new WVBoxLayout();
00110
00111
00112 WHBoxLayout *hLayout = new WHBoxLayout();
00113
00114
00115 hLayout->addWidget(messages, 1);
00116 messages->setStyleClass("chat-msgs");
00117
00118
00119 hLayout->addWidget(userList);
00120 userList->setStyleClass("chat-users");
00121
00122 hLayout->setResizable(0, true);
00123
00124
00125 vLayout->addLayout(hLayout, 1);
00126
00127
00128 vLayout->addWidget(messageEdit);
00129 messageEdit->setStyleClass("chat-noedit");
00130
00131
00132 hLayout = new WHBoxLayout();
00133
00134
00135 hLayout->addWidget(sendButton);
00136
00137
00138 hLayout->addWidget(logoutButton);
00139
00140
00141 hLayout->addStretch(1);
00142
00143
00144 vLayout->addLayout(hLayout);
00145
00146 setLayout(vLayout);
00147 }
00148
00149 bool SimpleChatWidget::startChat(const WString& user)
00150 {
00151 if (server_.login(user)) {
00152
00153
00154
00155 app_->enableUpdates(true);
00156
00157
00158 eventConnection_
00159 = server_.chatEvent().connect(this, &SimpleChatWidget::processChatEvent);
00160 user_ = user;
00161
00162 clear();
00163
00164 messages_ = new WContainerWidget();
00165 userList_ = new WContainerWidget();
00166 messageEdit_ = new WTextArea();
00167 messageEdit_->setRows(2);
00168 messageEdit_->setFocus();
00169
00170
00171 messages_->setOverflow(WContainerWidget::OverflowAuto);
00172 userList_->setOverflow(WContainerWidget::OverflowAuto);
00173
00174 sendButton_ = new WPushButton("Send");
00175 WPushButton *logoutButton = new WPushButton("Logout");
00176
00177 createLayout(messages_, userList_, messageEdit_, sendButton_, logoutButton);
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 clearInput_.setJavaScript
00192 ("function(o, e) { setTimeout(function() {"
00193 "" + messageEdit_->jsRef() + ".value='';"
00194 "}, 0); }");
00195
00196
00197 sendButton_->clicked().connect(this, &SimpleChatWidget::send);
00198 messageEdit_->enterPressed().connect(this, &SimpleChatWidget::send);
00199 sendButton_->clicked().connect(clearInput_);
00200 messageEdit_->enterPressed().connect(clearInput_);
00201 sendButton_->clicked().connect(messageEdit_, &WLineEdit::setFocus);
00202 messageEdit_->enterPressed().connect(messageEdit_, &WLineEdit::setFocus);
00203
00204
00205
00206 messageEdit_->enterPressed().preventDefaultAction();
00207
00208 logoutButton->clicked().connect(this, &SimpleChatWidget::logout);
00209
00210 WText *msg = new WText
00211 ("<div><span class='chat-info'>You are joining as "
00212 + user_ + ".</span></div>", messages_);
00213 msg->setStyleClass("chat-msg");
00214
00215 if (!userList_->parent()) {
00216 delete userList_;
00217 userList_ = 0;
00218 }
00219
00220 if (!sendButton_->parent()) {
00221 delete sendButton_;
00222 sendButton_ = 0;
00223 }
00224
00225 if (!logoutButton->parent())
00226 delete logoutButton;
00227
00228 updateUsers();
00229
00230 return true;
00231 } else
00232 return false;
00233 }
00234
00235 void SimpleChatWidget::send()
00236 {
00237 if (!messageEdit_->text().empty())
00238 server_.sendMessage(user_, messageEdit_->text());
00239 }
00240
00241 void SimpleChatWidget::updateUsers()
00242 {
00243 if (userList_) {
00244 userList_->clear();
00245
00246 SimpleChatServer::UserSet users = server_.users();
00247
00248 UserMap oldUsers = users_;
00249 users_.clear();
00250
00251 for (SimpleChatServer::UserSet::iterator i = users.begin();
00252 i != users.end(); ++i) {
00253 WCheckBox *w = new WCheckBox(*i, userList_);
00254 w->setInline(false);
00255
00256 UserMap::const_iterator j = oldUsers.find(*i);
00257 if (j != oldUsers.end())
00258 w->setChecked(j->second);
00259 else
00260 w->setChecked(true);
00261
00262 users_[*i] = w->isChecked();
00263 w->changed().connect(this, &SimpleChatWidget::updateUser);
00264
00265 if (*i == user_)
00266 w->setStyleClass("chat-self");
00267 }
00268 }
00269 }
00270
00271 void SimpleChatWidget::updateUser()
00272 {
00273 WCheckBox *b = dynamic_cast<WCheckBox *>(sender());
00274 users_[b->text()] = b->isChecked();
00275 }
00276
00277 void SimpleChatWidget::processChatEvent(const ChatEvent& event)
00278 {
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 WApplication::UpdateLock lock(app_);
00290
00291 if (lock) {
00292
00293
00294
00295
00296
00297
00298
00299
00300 bool needPush = false;
00301
00302
00303
00304
00305 if (event.type() != ChatEvent::Message) {
00306 if (event.type() == ChatEvent::Rename
00307 && event.user() == user_)
00308 user_ = event.data();
00309
00310 needPush = true;
00311 updateUsers();
00312 }
00313
00314 bool display = event.type() != ChatEvent::Message
00315 || !userList_
00316 || (users_.find(event.user()) != users_.end() && users_[event.user()]);
00317
00318 if (display) {
00319 needPush = true;
00320
00321 WText *w = new WText(event.formattedHTML(user_), messages_);
00322 w->setInline(false);
00323 w->setStyleClass("chat-msg");
00324
00325
00326
00327
00328 if (messages_->count() > 100)
00329 delete messages_->children()[0];
00330
00331
00332
00333
00334 app_->doJavaScript(messages_->jsRef() + ".scrollTop += "
00335 + messages_->jsRef() + ".scrollHeight;");
00336
00337
00338 if (event.user() != user_)
00339 messageReceived_.play();
00340 }
00341
00342 if (needPush)
00343 app_->triggerUpdate();
00344 }
00345 }