#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_->setFormatting(WText::PlainFormatting); 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", this)); 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(SLOT(sendButton_, WPushButton::disable)); 00163 messageEdit_->enterPressed.connect(SLOT(messageEdit_, WTextArea::disable)); 00164 messageEdit_->enterPressed.connect(SLOT(this, SimpleChatWidget::send)); 00165 00166 b->clicked.connect(SLOT(this, SimpleChatWidget::logout)); 00167 00168 WText *msg 00169 = new WText(false, 00170 "<span class='chat-info'>You are joining the conversation as " 00171 + user_ + "</span>", messages_); 00172 msg->setStyleClass("chat-msg"); 00173 00174 updateUsers(); 00175 00176 return true; 00177 } else 00178 return false; 00179 }
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 181 of file SimpleChatWidget.C.
00182 { 00183 if (!messageEdit_->text().empty()) { 00184 server_.sendMessage(user_, messageEdit_->text()); 00185 messageEdit_->setText(""); 00186 } 00187 00188 messageEdit_->enable(); 00189 messageEdit_->setFocus(); 00190 sendButton_->enable(); 00191 }
void SimpleChatWidget::updateUsers | ( | ) | [private] |
Definition at line 193 of file SimpleChatWidget.C.
00194 { 00195 userList_->clear(); 00196 00197 SimpleChatServer::UserSet users = server_.users(); 00198 00199 WString usersStr; 00200 00201 for (SimpleChatServer::UserSet::iterator i = users.begin(); 00202 i != users.end(); ++i) { 00203 if (*i == user_) 00204 usersStr += "<span class='chat-self'>" + *i + "</span><br />"; 00205 else 00206 usersStr += *i + "<br />"; 00207 } 00208 00209 userList_->addWidget(new WText(false, usersStr)); 00210 }
void SimpleChatWidget::processChatEvent | ( | const ChatEvent & | event | ) | [private] |
Definition at line 212 of file SimpleChatWidget.C.
00213 { 00214 /* 00215 * This is where the "server-push" happens. This method is called 00216 * when a new event or message needs to be notified to the user. In 00217 * general, it is called from another session. 00218 * 00219 * First, we take the lock to safely manipulate the UI outside of the 00220 * normal event loop. 00221 */ 00222 00223 WApplication::UpdateLock lock = app_->getUpdateLock(); 00224 00225 WText *w = new WText(false, event.formattedHTML(user_), messages_); 00226 w->setStyleClass("chat-msg"); 00227 00228 /* no more than 100 messages back-log */ 00229 if (messages_->count() > 100) 00230 delete messages_->children()[0]; 00231 00232 if (event.type() != ChatEvent::Message) 00233 updateUsers(); 00234 00235 /* 00236 * little javascript trick to make sure we scroll along with new content 00237 */ 00238 app_->doJavaScript(messages_->jsRef() + ".scrollTop += " 00239 + messages_->jsRef() + ".scrollHeight;"); 00240 00241 app_->triggerUpdate(); 00242 }
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.