#include <SimpleChatWidget.h>
Public Member Functions | |
SimpleChatWidget (SimpleChatServer &server, Wt::WContainerWidget *parent=0) | |
Create a chat widget that will connect to the given server. | |
~SimpleChatWidget () | |
Delete a chat widget. | |
void | letLogin () |
Show a simple login screen. | |
bool | startChat (const Wt::WString &user) |
Start a chat for the given user. | |
Private Member Functions | |
void | login () |
void | logout () |
void | send () |
void | updateUsers () |
void | processChatEvent (const ChatEvent &event) |
void | onEditBlur () |
void | onEditFocus () |
Private Attributes | |
SimpleChatServer & | server_ |
Wt::WApplication * | app_ |
Wt::WString | user_ |
Wt::WLineEdit * | userNameEdit_ |
Wt::WText * | statusMsg_ |
Wt::WContainerWidget * | messages_ |
Wt::WContainerWidget * | messageEditArea_ |
Wt::WTextArea * | messageEdit_ |
Wt::WPushButton * | sendButton_ |
Wt::WContainerWidget * | userList_ |
boost::signals::connection | eventConnection_ |
Definition at line 31 of file SimpleChatWidget.h.
SimpleChatWidget::SimpleChatWidget | ( | SimpleChatServer & | server, | |
Wt::WContainerWidget * | parent = 0 | |||
) |
Create a chat widget that will connect to the given server.
Definition at line 24 of file SimpleChatWidget.C.
00026 : WContainerWidget(parent), 00027 server_(server), 00028 app_(WApplication::instance()) 00029 { 00030 user_ = server_.suggestGuest(); 00031 letLogin(); 00032 00033 app_->enableUpdates(); 00034 }
SimpleChatWidget::~SimpleChatWidget | ( | ) |
Delete a chat widget.
Definition at line 36 of file SimpleChatWidget.C.
00037 { 00038 logout(); 00039 }
void SimpleChatWidget::letLogin | ( | ) |
Show a simple login screen.
Definition at line 41 of file SimpleChatWidget.C.
00042 { 00043 clear(); 00044 00045 WVBoxLayout *vLayout = new WVBoxLayout(); 00046 setLayout(vLayout, AlignLeft | AlignTop); 00047 00048 WHBoxLayout *hLayout = new WHBoxLayout(); 00049 vLayout->addLayout(hLayout); 00050 00051 hLayout->addWidget(new WLabel("User name:"), 0, AlignMiddle); 00052 hLayout->addWidget(userNameEdit_ = new WLineEdit(user_), 0, AlignMiddle); 00053 userNameEdit_->setFocus(); 00054 00055 WPushButton *b = new WPushButton("Login"); 00056 hLayout->addWidget(b, 0, AlignMiddle); 00057 hLayout->addStretch(1); 00058 00059 b->clicked().connect(SLOT(this, SimpleChatWidget::login)); 00060 userNameEdit_->enterPressed().connect(SLOT(this, SimpleChatWidget::login)); 00061 00062 vLayout->addWidget(statusMsg_ = new WText()); 00063 statusMsg_->setTextFormat(PlainText); 00064 }
bool SimpleChatWidget::startChat | ( | const Wt::WString & | user | ) |
Start a chat for the given user.
Returns false if the user could not login.
Definition at line 84 of file SimpleChatWidget.C.
00085 { 00086 if (server_.login(user)) { 00087 eventConnection_ 00088 = server_.chatEvent().connect(SLOT(this, 00089 SimpleChatWidget::processChatEvent)); 00090 user_ = user; 00091 00092 clear(); 00093 00094 /* 00095 * Create a vertical layout, which will hold 3 rows, 00096 * organized like this: 00097 * 00098 * WVBoxLayout 00099 * -------------------------------------------- 00100 * | nested WHBoxLayout (vertical stretch=1) | 00101 * | | | 00102 * | messages | userslist | 00103 * | (horizontal stretch=1) | | 00104 * | | | 00105 * -------------------------------------------- 00106 * | message edit area | 00107 * -------------------------------------------- 00108 * | WHBoxLayout | 00109 * | send | logout | stretch = 1 | 00110 * -------------------------------------------- 00111 */ 00112 WVBoxLayout *vLayout = new WVBoxLayout(); 00113 00114 // Create a horizontal layout for the messages | userslist. 00115 WHBoxLayout *hLayout = new WHBoxLayout(); 00116 00117 // Add widget to horizontal layout with stretch = 1 00118 hLayout->addWidget(messages_ = new WContainerWidget(), 1); 00119 messages_->setStyleClass("chat-msgs"); 00120 // Display scroll bars if contents overflows 00121 messages_->setOverflow(WContainerWidget::OverflowAuto); 00122 00123 // Add another widget to hirozontal layout with stretch = 0 00124 hLayout->addWidget(userList_ = new WContainerWidget()); 00125 userList_->setStyleClass("chat-users"); 00126 userList_->setOverflow(WContainerWidget::OverflowAuto); 00127 00128 // Add nested layout to vertical layout with stretch = 1 00129 vLayout->addLayout(hLayout, 1); 00130 00131 // Add widget to vertical layout with stretch = 0 00132 vLayout->addWidget(messageEdit_ = new WTextArea()); 00133 messageEdit_->setStyleClass("chat-noedit"); 00134 messageEdit_->setRows(2); 00135 messageEdit_->setFocus(); 00136 00137 // Create a horizontal layout for the buttons. 00138 hLayout = new WHBoxLayout(); 00139 00140 // Add button to horizontal layout with stretch = 0 00141 hLayout->addWidget(sendButton_ = new WPushButton("Send")); 00142 WPushButton *b; 00143 00144 // Add button to horizontal layout with stretch = 0 00145 hLayout->addWidget(b = new WPushButton("Logout")); 00146 00147 // Add stretching spacer to horizontal layout 00148 hLayout->addStretch(1); 00149 00150 // Add nested layout to vertical layout with stretch = 0 00151 vLayout->addLayout(hLayout); 00152 00153 setLayout(vLayout); 00154 00155 /* 00156 * Connect event handlers 00157 */ 00158 sendButton_->clicked().connect(SLOT(sendButton_, WPushButton::disable)); 00159 sendButton_->clicked().connect(SLOT(messageEdit_, WTextArea::disable)); 00160 sendButton_->clicked().connect(SLOT(this, SimpleChatWidget::send)); 00161 00162 messageEdit_->enterPressed().connect 00163 (SLOT(sendButton_, WPushButton::disable)); 00164 messageEdit_->enterPressed().connect 00165 (SLOT(messageEdit_, WTextArea::disable)); 00166 messageEdit_->enterPressed().connect 00167 (SLOT(this, SimpleChatWidget::send)); 00168 00169 b->clicked().connect(SLOT(this, SimpleChatWidget::logout)); 00170 00171 WText *msg = new WText 00172 ("<div><span class='chat-info'>You are joining the conversation as " 00173 + user_ + "</span></div>", messages_); 00174 msg->setStyleClass("chat-msg"); 00175 00176 updateUsers(); 00177 00178 return true; 00179 } else 00180 return false; 00181 }
void SimpleChatWidget::login | ( | ) | [private] |
Definition at line 66 of file SimpleChatWidget.C.
00067 { 00068 WString name = WWebWidget::escapeText(userNameEdit_->text()); 00069 00070 if (!startChat(name)) 00071 statusMsg_->setText("Sorry, name '" + name + "' is already taken."); 00072 }
void SimpleChatWidget::logout | ( | ) | [private] |
Definition at line 74 of file SimpleChatWidget.C.
00075 { 00076 if (eventConnection_.connected()) { 00077 eventConnection_.disconnect(); // do not listen for more events 00078 server_.logout(user_); 00079 00080 letLogin(); 00081 } 00082 }
void SimpleChatWidget::send | ( | ) | [private] |
Definition at line 183 of file SimpleChatWidget.C.
00184 { 00185 if (!messageEdit_->text().empty()) { 00186 server_.sendMessage(user_, messageEdit_->text()); 00187 messageEdit_->setText(""); 00188 } 00189 00190 messageEdit_->enable(); 00191 messageEdit_->setFocus(); 00192 sendButton_->enable(); 00193 }
void SimpleChatWidget::updateUsers | ( | ) | [private] |
Definition at line 195 of file SimpleChatWidget.C.
00196 { 00197 userList_->clear(); 00198 00199 SimpleChatServer::UserSet users = server_.users(); 00200 00201 WString usersStr; 00202 00203 for (SimpleChatServer::UserSet::iterator i = users.begin(); 00204 i != users.end(); ++i) { 00205 if (*i == user_) 00206 usersStr += "<div><span class='chat-self'>" + *i + "</span></div>"; 00207 else 00208 usersStr += "<div>" + *i + "</div>"; 00209 } 00210 00211 userList_->addWidget(new WText(usersStr)); 00212 }
void SimpleChatWidget::processChatEvent | ( | const ChatEvent & | event | ) | [private] |
Definition at line 214 of file SimpleChatWidget.C.
00215 { 00216 /* 00217 * This is where the "server-push" happens. This method is called 00218 * when a new event or message needs to be notified to the user. In 00219 * general, it is called from another session. 00220 * 00221 * First, we take the lock to safely manipulate the UI outside of the 00222 * normal event loop. 00223 */ 00224 00225 WApplication::UpdateLock lock = app_->getUpdateLock(); 00226 00227 WText *w = new WText(event.formattedHTML(user_), messages_); 00228 w->setInline(false); 00229 w->setStyleClass("chat-msg"); 00230 00231 /* no more than 100 messages back-log */ 00232 if (messages_->count() > 100) 00233 delete messages_->children()[0]; 00234 00235 if (event.type() != ChatEvent::Message) 00236 updateUsers(); 00237 00238 /* 00239 * little javascript trick to make sure we scroll along with new content 00240 */ 00241 app_->doJavaScript(messages_->jsRef() + ".scrollTop += " 00242 + messages_->jsRef() + ".scrollHeight;"); 00243 00244 app_->triggerUpdate(); 00245 }
void SimpleChatWidget::onEditBlur | ( | ) | [private] |
void SimpleChatWidget::onEditFocus | ( | ) | [private] |
SimpleChatServer& SimpleChatWidget::server_ [private] |
Definition at line 53 of file SimpleChatWidget.h.
Wt::WApplication* SimpleChatWidget::app_ [private] |
Definition at line 54 of file SimpleChatWidget.h.
Wt::WString SimpleChatWidget::user_ [private] |
Definition at line 56 of file SimpleChatWidget.h.
Wt::WLineEdit* SimpleChatWidget::userNameEdit_ [private] |
Definition at line 58 of file SimpleChatWidget.h.
Wt::WText* SimpleChatWidget::statusMsg_ [private] |
Definition at line 59 of file SimpleChatWidget.h.
Wt::WContainerWidget* SimpleChatWidget::messages_ [private] |
Definition at line 61 of file SimpleChatWidget.h.
Definition at line 62 of file SimpleChatWidget.h.
Wt::WTextArea* SimpleChatWidget::messageEdit_ [private] |
Definition at line 63 of file SimpleChatWidget.h.
Wt::WPushButton* SimpleChatWidget::sendButton_ [private] |
Definition at line 64 of file SimpleChatWidget.h.
Wt::WContainerWidget* SimpleChatWidget::userList_ [private] |
Definition at line 65 of file SimpleChatWidget.h.
boost::signals::connection SimpleChatWidget::eventConnection_ [private] |
Definition at line 67 of file SimpleChatWidget.h.