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(this, &SimpleChatWidget::login);
00066 userNameEdit_->enterPressed().connect(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
00094 eventConnection_
00095 = server_.chatEvent().connect(this, &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(this, &SimpleChatWidget::send);
00182 messageEdit_->enterPressed().connect(this, &SimpleChatWidget::send);
00183 sendButton_->clicked().connect(clearInput_);
00184 messageEdit_->enterPressed().connect(clearInput_);
00185 sendButton_->clicked().connect(messageEdit_, &WLineEdit::setFocus);
00186 messageEdit_->enterPressed().connect(messageEdit_, &WLineEdit::setFocus);
00187
00188
00189
00190 messageEdit_->enterPressed().preventDefaultAction();
00191
00192 b->clicked().connect(this, &SimpleChatWidget::logout);
00193
00194 WText *msg = new WText
00195 ("<div><span class='chat-info'>You are joining the conversation as "
00196 + user_ + "</span></div>", messages_);
00197 msg->setStyleClass("chat-msg");
00198
00199 updateUsers();
00200
00201 return true;
00202 } else
00203 return false;
00204 }
00205
00206 void SimpleChatWidget::send()
00207 {
00208 if (!messageEdit_->text().empty())
00209 server_.sendMessage(user_, messageEdit_->text());
00210 }
00211
00212 void SimpleChatWidget::updateUsers()
00213 {
00214 userList_->clear();
00215
00216 SimpleChatServer::UserSet users = server_.users();
00217
00218 UserMap oldUsers = users_;
00219 users_.clear();
00220
00221 for (SimpleChatServer::UserSet::iterator i = users.begin();
00222 i != users.end(); ++i) {
00223 WCheckBox *w = new WCheckBox(*i, userList_);
00224 w->setInline(false);
00225
00226 UserMap::const_iterator j = oldUsers.find(*i);
00227 if (j != oldUsers.end())
00228 w->setChecked(j->second);
00229 else
00230 w->setChecked(true);
00231
00232 users_[*i] = w->isChecked();
00233 w->changed().connect(this, &SimpleChatWidget::updateUser);
00234
00235 if (*i == user_)
00236 w->setStyleClass("chat-self");
00237 }
00238 }
00239
00240 void SimpleChatWidget::updateUser()
00241 {
00242 WCheckBox *b = dynamic_cast<WCheckBox *>(sender());
00243 users_[b->text()] = b->isChecked();
00244 }
00245
00246 void SimpleChatWidget::processChatEvent(const ChatEvent& event)
00247 {
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 WApplication::UpdateLock lock(app_);
00259
00260 if (lock) {
00261
00262
00263
00264
00265
00266
00267
00268
00269 bool needPush = false;
00270
00271
00272
00273
00274 if (event.type() != ChatEvent::Message) {
00275 needPush = true;
00276 updateUsers();
00277 }
00278
00279 bool display = event.type() != ChatEvent::Message
00280 || (users_.find(event.user()) != users_.end() && users_[event.user()]);
00281
00282 if (display) {
00283 needPush = true;
00284
00285 WText *w = new WText(event.formattedHTML(user_), messages_);
00286 w->setInline(false);
00287 w->setStyleClass("chat-msg");
00288
00289
00290
00291
00292 if (messages_->count() > 100)
00293 delete messages_->children()[0];
00294
00295
00296
00297
00298 app_->doJavaScript(messages_->jsRef() + ".scrollTop += "
00299 + messages_->jsRef() + ".scrollHeight;");
00300
00301
00302 if (event.user() != user_)
00303 messageReceived_.play();
00304 }
00305
00306 if (needPush)
00307 app_->triggerUpdate();
00308 }
00309 }