00001
00002
00003
00004
00005
00006
00007 #include <fstream>
00008 #include <iostream>
00009
00010 #include <boost/tokenizer.hpp>
00011
00012 #include <WApplication>
00013 #include <WDatePicker>
00014 #include <WCalendar>
00015 #include <WEnvironment>
00016 #include <WIconPair>
00017 #include <WImage>
00018 #include <WLineEdit>
00019 #include <WMenu>
00020 #include <WPushButton>
00021 #include <WStackedWidget>
00022 #include <WTabWidget>
00023 #include <WTable>
00024 #include <WTableCell>
00025 #include <WText>
00026 #include <WTreeNode>
00027 #include <WViewWidget>
00028
00029 #include "Home.h"
00030 #include "TreeListExample.h"
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 template <typename Function>
00042 class DeferredWidget : public WContainerWidget
00043 {
00044 public:
00045 DeferredWidget(Function f)
00046 : f_(f) { }
00047
00048 private:
00049 void load() {
00050 addWidget(f_());
00051 }
00052
00053 Function f_;
00054 };
00055
00056 template <typename Function>
00057 DeferredWidget<Function> *deferCreate(Function f)
00058 {
00059 return new DeferredWidget<Function>(f);
00060 }
00061
00062
00063 class Div : public WContainerWidget
00064 {
00065 public:
00066 Div(WContainerWidget *parent, const std::string& id)
00067 : WContainerWidget(parent)
00068 {
00069 setId(id);
00070 }
00071 };
00072
00073 Home::Home(WContainerWidget *parent)
00074 : WContainerWidget(parent)
00075 {
00076 Div *topWrapper = new Div(this, "top_wrapper");
00077 Div *topContent = new Div(topWrapper, "top_content");
00078 new Div(topContent, "top_languages");
00079
00080
00081
00082
00083
00084
00085 WText *topWt = new WText(tr("top_wt"), topContent);
00086 topWt->setInline(false);
00087 topWt->setId("top_wt");
00088
00089 Div *bannerWrapper = new Div(this, "banner_wrapper");
00090 Div *bannerContent = new Div(bannerWrapper, "banner_content");
00091 new Div(bannerContent, "banner");
00092 if (!wApp->environment().javaScript()) {
00093 new WText("<i>(no JavaScript support detected)</i>", bannerContent);
00094 }
00095
00096 Div *mainWrapper = new Div(this, "main_wrapper");
00097 Div *mainContent = new Div(mainWrapper, "main_content");
00098 Div *mainMenu = new Div(mainContent, "main_menu");
00099
00100 WStackedWidget *contents = new WStackedWidget();
00101 contents->setId("main_page");
00102
00103 WMenu *menu = new WMenu(contents, Vertical, mainMenu);
00104 menu->setRenderAsList(true);
00105 menu->enableBrowserHistory("main");
00106
00107 menu->addItem("Introduction", introduction());
00108 menu->addItem("News", deferCreate(boost::bind(&Home::news, this)),
00109 WMenuItem::PreLoading);
00110 menu->addItem("Features", wrapViewOrDefer(&Home::features),
00111 WMenuItem::PreLoading);
00112 menu->addItem("Documentation", wrapViewOrDefer(&Home::documentation),
00113 WMenuItem::PreLoading);
00114 menu->addItem("Examples", examples(), WMenuItem::PreLoading);
00115 menu->addItem("Download", deferCreate(boost::bind(&Home::download, this)),
00116 WMenuItem::PreLoading);
00117 menu->addItem("Community", wrapViewOrDefer(&Home::community),
00118 WMenuItem::PreLoading);
00119
00120 changeTitle(menu->currentItem());
00121
00122 menu->itemSelectRendered.connect(SLOT(this, Home::changeTitle));
00123
00124 sideBarContent_ = new WContainerWidget(mainMenu);
00125
00126 mainContent->addWidget(contents);
00127 WContainerWidget *clearAll = new WContainerWidget(mainContent);
00128 clearAll->setStyleClass("clearall");
00129
00130 WText *footerWrapper = new WText(tr("footer_wrapper"), this);
00131 footerWrapper->setInline(false);
00132 footerWrapper->setId("footer_wrapper");
00133 }
00134
00135 void Home::changeTitle(WMenuItem *item)
00136 {
00137 wApp->setTitle(L"Wt, C++ Web Toolkit - " + item->text().value());
00138 }
00139
00140 WWidget *Home::introduction()
00141 {
00142 return new WText(tr("home.intro"));
00143 }
00144
00145 void Home::refresh()
00146 {
00147 readNews(recentNews_, "latest-news.txt");
00148 readNews(historicalNews_, "historical-news.txt");
00149 readReleases(releases_, "releases.txt");
00150
00151 WContainerWidget::refresh();
00152 }
00153
00154 WWidget *Home::news()
00155 {
00156 WContainerWidget *result = new WContainerWidget();
00157
00158 result->addWidget(new WText("<h3>News</h3>"));
00159
00160 result->addWidget(new WText("<h4><span>Latest News</span></h4>"));
00161 recentNews_ = new WTable();
00162 readNews(recentNews_, "latest-news.txt");
00163 result->addWidget(recentNews_);
00164
00165 result->addWidget(new WText("<h4><span>Historical News</span></h4>"));
00166 historicalNews_ = new WTable();
00167 readNews(historicalNews_, "historical-news.txt");
00168 result->addWidget(historicalNews_);
00169
00170 return result;
00171 }
00172
00173 WWidget *Home::status()
00174 {
00175 return new WText(tr("home.status"));
00176 }
00177
00178 WWidget *Home::features()
00179 {
00180 return new WText(tr("home.features"));
00181 }
00182
00183 WWidget *Home::documentation()
00184 {
00185 return new WText(tr("home.documentation"));
00186 }
00187
00188 WWidget *Home::helloWorldExample()
00189 {
00190 WContainerWidget *result = new WContainerWidget();
00191
00192 new WText(tr("home.examples.hello"), result);
00193
00194 WTreeNode *tree = makeTreeMap("Hello world", 0);
00195 makeTreeFile("hello.C", tree);
00196
00197 tree->expand();
00198
00199 result->addWidget(tree);
00200
00201 return result;
00202 }
00203
00204 WWidget *Home::homepageExample()
00205 {
00206 WContainerWidget *result = new WContainerWidget();
00207
00208 new WText(tr("home.examples.wt"), result);
00209
00210 WTreeNode *tree = makeTreeMap("Wt Homepage", 0);
00211 WTreeNode *home = makeTreeMap("class Home", tree);
00212 makeTreeFile("Home.h", home);
00213 makeTreeFile("Home.C", home);
00214 WTreeNode *treeexample = makeTreeMap("class TreeListExample", tree);
00215 makeTreeFile("TreeListExample.h", treeexample);
00216 makeTreeFile("TreeListExample.C", treeexample);
00217 makeTreeFile("wt-home.xml", tree);
00218
00219 tree->expand();
00220
00221 result->addWidget(tree);
00222
00223 return result;
00224 }
00225
00226 WWidget *Home::formExample()
00227 {
00228 WContainerWidget *result = new WContainerWidget();
00229
00230 new WText(tr("home.examples.form"), result);
00231
00232 WTreeNode *tree = makeTreeMap("Form example", 0);
00233 WTreeNode *form = makeTreeMap("class Form", tree);
00234 makeTreeFile("Form.h", form);
00235 makeTreeFile("Form.C", form);
00236 WTreeNode *formexample = makeTreeMap("class FormExample", tree);
00237 makeTreeFile("FormExample.h", formexample);
00238 makeTreeFile("FormExample.C", formexample);
00239 WTreeNode *datevalidator = makeTreeMap("class DateValidator", tree);
00240 makeTreeFile("DateValidator.h", datevalidator);
00241 makeTreeFile("DateValidator.C", datevalidator);
00242 makeTreeFile("form-example.xml", tree);
00243 makeTreeFile("form-example_nl.xml", tree);
00244
00245 tree->expand();
00246
00247 result->addWidget(tree);
00248
00249 return result;
00250 }
00251
00252 WWidget *Home::treelistExample()
00253 {
00254 WContainerWidget *result = new WContainerWidget();
00255
00256 new WText(tr("home.examples.treelist"), result);
00257 new TreeListExample(result);
00258 new WText(tr("home.examples.treelist-remarks"), result);
00259
00260 return result;
00261 }
00262
00263 WWidget *Home::hangmanExample()
00264 {
00265 WContainerWidget *result = new WContainerWidget();
00266
00267 new WText(tr("home.examples.hangman"), result);
00268
00269 WTreeNode *tree = makeTreeMap("Hangman game", 0);
00270 tree->setLoadPolicy(WTreeNode::PreLoading);
00271
00272 WTreeNode *widgets = makeTreeMap("Widgets", tree);
00273 WTreeNode *loginwidget = makeTreeMap("class LoginWidget", widgets);
00274 makeTreeFile("LoginWidget.h", loginwidget);
00275 makeTreeFile("LoginWidget.C", loginwidget);
00276 WTreeNode *hangmanwidget = makeTreeMap("class HangmanWidget", widgets);
00277 makeTreeFile("HangmanWidget.h", hangmanwidget);
00278 makeTreeFile("HangmanWidget.C", hangmanwidget);
00279 WTreeNode *highscoreswidget = makeTreeMap("class HighScoresWidget", widgets);
00280 makeTreeFile("HighScoresWidget.h", highscoreswidget);
00281 makeTreeFile("HighScoresWidget.C", highscoreswidget);
00282 WTreeNode *hangmangame = makeTreeMap("class HangmanGame", widgets);
00283 makeTreeFile("HangmanGame.h", hangmangame);
00284 makeTreeFile("HangmanGame.C", hangmangame);
00285 WTreeNode *other = makeTreeMap("Other", tree);
00286 WTreeNode *hangmandb = makeTreeMap("class HangmanDb", other);
00287 makeTreeFile("HangmanDb.h", hangmandb);
00288 makeTreeFile("HangmanDb.C", hangmandb);
00289 WTreeNode *dictionary = makeTreeMap("class Dictionary", other);
00290 makeTreeFile("Dictionary.h", dictionary);
00291 makeTreeFile("Dictionary.C", dictionary);
00292 makeTreeFile("hangman.C", other);
00293
00294 tree->expand();
00295
00296 result->addWidget(tree);
00297
00298 return result;
00299 }
00300
00301 WWidget *Home::composerExample()
00302 {
00303 WContainerWidget *result = new WContainerWidget();
00304
00305 new WText(tr("home.examples.composer"), result);
00306
00307 WTreeNode *tree = makeTreeMap("Mail composer example", 0);
00308
00309 WTreeNode *classMap;
00310 classMap = makeTreeMap("class AddresseeEdit", tree);
00311 makeTreeFile("AddresseeEdit.h", classMap);
00312 makeTreeFile("AddresseeEdit.C", classMap);
00313 classMap = makeTreeMap("class AttachmentEdit", tree);
00314 makeTreeFile("AttachmentEdit.h", classMap);
00315 makeTreeFile("AttachmentEdit.C", classMap);
00316 classMap = makeTreeMap("class ComposeExample", tree);
00317 makeTreeFile("ComposeExample.h", classMap);
00318 makeTreeFile("ComposeExample.C", classMap);
00319 classMap = makeTreeMap("class Composer", tree);
00320 makeTreeFile("Composer.h", classMap);
00321 makeTreeFile("Composer.C", classMap);
00322 classMap = makeTreeMap("class ContactSuggestions", tree);
00323 makeTreeFile("ContactSuggestions.h", classMap);
00324 makeTreeFile("ContactSuggestions.C", classMap);
00325 classMap = makeTreeMap("class Label", tree);
00326 makeTreeFile("Label.h", classMap);
00327 makeTreeFile("Label.C", classMap);
00328 classMap = makeTreeMap("class Option", tree);
00329 makeTreeFile("Option.h", classMap);
00330 makeTreeFile("Option.C", classMap);
00331 classMap = makeTreeMap("class OptionList", tree);
00332 makeTreeFile("OptionList.h", classMap);
00333 makeTreeFile("OptionList.C", classMap);
00334 makeTreeFile("Contact.h", tree);
00335 makeTreeFile("Attachment.h", tree);
00336 makeTreeFile("composer.xml", tree);
00337 makeTreeFile("composer.css", tree);
00338
00339 tree->expand();
00340
00341 result->addWidget(tree);
00342
00343 return result;
00344 }
00345
00346 WWidget *Home::dragdropExample()
00347 {
00348 WContainerWidget *result = new WContainerWidget();
00349
00350 new WText(tr("home.examples.dragdrop"), result);
00351
00352 WTreeNode *tree = makeTreeMap("DragDrop example", 0);
00353
00354 WTreeNode *classMap;
00355 classMap = makeTreeMap("class Character", tree);
00356 makeTreeFile("Character.h", classMap);
00357 makeTreeFile("Character.C", classMap);
00358 makeTreeFile("DragExample.C", tree);
00359 makeTreeFile("dragdrop.css", tree);
00360
00361 tree->expand();
00362
00363 result->addWidget(tree);
00364
00365 return result;
00366 }
00367
00368 WWidget *Home::chatExample()
00369 {
00370 WContainerWidget *result = new WContainerWidget();
00371
00372 new WText(tr("home.examples.chat"), result);
00373
00374 WTreeNode *tree = makeTreeMap("Chat example", 0);
00375
00376 WTreeNode *classMap;
00377 classMap = makeTreeMap("class SimpleChatWidget", tree);
00378 makeTreeFile("SimpleChatWidget.h", classMap);
00379 makeTreeFile("SimpleChatWidget.C", classMap);
00380 classMap = makeTreeMap("class SimpleChatServer", tree);
00381 makeTreeFile("SimpleChatServer.h", classMap);
00382 makeTreeFile("SimpleChatServer.C", classMap);
00383 makeTreeFile("simpleChat.C", tree);
00384 makeTreeFile("simplechat.css", tree);
00385 makeTreeFile("simplechat.xml", tree);
00386
00387 tree->expand();
00388
00389 result->addWidget(tree);
00390
00391 return result;
00392 }
00393
00394 WWidget *Home::fileExplorerExample()
00395 {
00396 WContainerWidget *result = new WContainerWidget();
00397
00398 new WText(tr("home.examples.fileexplorer"), result);
00399
00400 WTreeNode *tree = makeTreeMap("File explorer example", 0);
00401
00402 WTreeNode *classMap;
00403 classMap = makeTreeMap("class FileTreeTableNode", tree);
00404 makeTreeFile("FileTreeTableNode.h", classMap);
00405 makeTreeFile("FileTreeTableNode.C", classMap);
00406 classMap = makeTreeMap("class FileTreeTable", tree);
00407 makeTreeFile("FileTreeTable.h", classMap);
00408 makeTreeFile("FileTreeTable.C", classMap);
00409 makeTreeFile("FileTreeExample.C", tree);
00410 makeTreeFile("filetree.css", tree);
00411
00412 tree->expand();
00413
00414 result->addWidget(tree);
00415
00416 return result;
00417 }
00418
00419 WWidget *Home::calendarExample()
00420 {
00421 WContainerWidget *result = new WContainerWidget();
00422
00423 new WText(tr("home.examples.calendar"), result);
00424
00425 new WText("<p>A field for editing a date in conjunction "
00426 "with a WDatePicker:</p>", result);
00427
00428 WTable *tab = new WTable(result);
00429 new WText("Please enter your birth date: ", tab->elementAt(0, 0));
00430 WLineEdit *dateEdit = new WLineEdit(tab->elementAt(0, 1));
00431 dateEdit->setMargin(5, Right);
00432
00433 new WDatePicker(new WPushButton("..."), dateEdit,
00434 false, tab->elementAt(0, 1));
00435 tab->elementAt(0, 0)->setPadding(8);
00436 tab->elementAt(0, 1)->setPadding(8);
00437
00438 new WText("<p>A plain calendar:</p>", result);
00439 WCalendar *cal = new WCalendar(false, result);
00440 cal->setMargin(8);
00441
00442 new WText("<p>A calendar with multiple selection:</p>", result);
00443 cal = new WCalendar(false, result);
00444 cal->setMultipleSelection(true);
00445 cal->setMargin(8);
00446
00447
00448 return result;
00449 }
00450
00451 WWidget *Home::wrapViewOrDefer(WWidget *(Home::*createWidget)())
00452 {
00453
00454
00455
00456
00457
00458
00459
00460 if (wApp->environment().javaScript())
00461 return makeStaticModel(boost::bind(createWidget, this));
00462 else
00463 return deferCreate(boost::bind(createWidget, this));
00464 }
00465
00466 WWidget *Home::examples()
00467 {
00468 WContainerWidget *result = new WContainerWidget();
00469
00470 result->addWidget(new WText(tr("home.examples")));
00471
00472 WTabWidget *exampleTabs = new WTabWidget(result);
00473 exampleTabs->enableBrowserHistory("example");
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 exampleTabs->addTab(wrapViewOrDefer(&Home::helloWorldExample),
00493 "Hello world");
00494 exampleTabs->addTab(wrapViewOrDefer(&Home::formExample),
00495 "Form");
00496 exampleTabs->addTab(wrapViewOrDefer(&Home::homepageExample),
00497 "Wt homepage");
00498 exampleTabs->addTab(deferCreate(boost::bind(&Home::treelistExample, this)),
00499 "Treelist");
00500 exampleTabs->addTab(wrapViewOrDefer(&Home::hangmanExample),
00501 "Hangman");
00502 exampleTabs->addTab(wrapViewOrDefer(&Home::chatExample),
00503 "Chat");
00504 exampleTabs->addTab(wrapViewOrDefer(&Home::composerExample),
00505 "Mail composer");
00506 exampleTabs->addTab(wrapViewOrDefer(&Home::dragdropExample),
00507 "Drag & Drop");
00508 exampleTabs->addTab(wrapViewOrDefer(&Home::fileExplorerExample),
00509 "File explorer");
00510 exampleTabs->addTab(deferCreate(boost::bind(&Home::calendarExample, this)),
00511 "Calendar");
00512
00513 return result;
00514 }
00515
00516 WWidget *Home::download()
00517 {
00518 WContainerWidget *result = new WContainerWidget();
00519 result->addWidget(new WText("<h3><span>Download</span></h3>"));
00520 result->addWidget(new WText(tr("home.download.license")));
00521 result->addWidget(new WText(tr("home.download.requirements")));
00522 result->addWidget(new WText("<h4>Available packages</h4>"));
00523
00524 releases_ = new WTable();
00525 readReleases(releases_, "releases.txt");
00526 result->addWidget(releases_);
00527
00528 result->addWidget
00529 (new WText("<p>Older releases are still available at "
00530 + href("http://sourceforge.net/project/showfiles.php?"
00531 "group_id=153710#files",
00532 "sourceforge.net")
00533 + "</p>"));
00534
00535 return result;
00536 }
00537
00538 std::string Home::href(const std::string url, const std::string description)
00539 {
00540 return "<a href=\"" + url + "\" TARGET=\"_blank\">" + description + "</a>";
00541 }
00542
00543 WWidget *Home::community()
00544 {
00545 return new WText(tr("home.community"));
00546 }
00547
00548 void Home::readNews(WTable *newsTable, const std::string newsfile)
00549 {
00550 std::ifstream f(newsfile.c_str());
00551
00552 newsTable->clear();
00553
00554 int row = 0;
00555
00556 while (f) {
00557 std::string line;
00558 getline(f, line);
00559
00560 if (f) {
00561 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00562 CsvTokenizer;
00563 CsvTokenizer tok(line);
00564
00565 CsvTokenizer::iterator i=tok.begin();
00566
00567 newsTable->elementAt(row, 0)->
00568 addWidget(new WText("<p><b>" + *i + "</b></p>"));
00569 newsTable->elementAt(row, 0)
00570 ->setContentAlignment(AlignCenter | AlignTop);
00571 newsTable->elementAt(row, 0)
00572 ->resize(WLength(16, WLength::FontEx), WLength());
00573 newsTable
00574 ->elementAt(row, 1)->addWidget(new WText("<p>" + *(++i) + "</p>"));
00575
00576 ++row;
00577 }
00578 }
00579 }
00580
00581 void Home::readReleases(WTable *releaseTable, const std::string releasefile)
00582 {
00583 std::ifstream f(releasefile.c_str());
00584
00585 releaseTable->clear();
00586
00587 releaseTable->elementAt(0, 0)->addWidget(new WText("<b>Version</b>"));
00588 releaseTable->elementAt(0, 1)->addWidget(new WText("<b>Date</b>"));
00589 releaseTable->elementAt(0, 2)->addWidget(new WText("<b>Description</b>"));
00590
00591 releaseTable->elementAt(0, 0)->resize(WLength(10, WLength::FontEx),
00592 WLength());
00593 releaseTable->elementAt(0, 1)->resize(WLength(15, WLength::FontEx),
00594 WLength());
00595
00596 int row = 1;
00597
00598 while (f) {
00599 std::string line;
00600 getline(f, line);
00601
00602 if (f) {
00603 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00604 CsvTokenizer;
00605 CsvTokenizer tok(line);
00606
00607 CsvTokenizer::iterator i=tok.begin();
00608
00609 std::string version = *i;
00610 releaseTable->elementAt(row, 0)->addWidget
00611 (new WText(href("http://prdownloads.sourceforge.net/witty/wt-"
00612 + version + ".tar.gz?download", "Wt " + version)));
00613 releaseTable->elementAt(row, 1)->addWidget(new WText(*(++i)));
00614 releaseTable->elementAt(row, 2)->addWidget(new WText(*(++i)));
00615
00616 ++row;
00617 }
00618 }
00619 }
00620
00621 WTreeNode *Home::makeTreeMap(const std::string name, WTreeNode *parent)
00622 {
00623 WIconPair *labelIcon
00624 = new WIconPair("icons/yellow-folder-closed.png",
00625 "icons/yellow-folder-open.png", false);
00626
00627 WTreeNode *node = new WTreeNode(name, labelIcon, parent);
00628 node->label()->setFormatting(WText::PlainFormatting);
00629
00630 if (!parent) {
00631 node->setImagePack("icons/");
00632 node->expand();
00633 node->setLoadPolicy(WTreeNode::NextLevelLoading);
00634 }
00635
00636 return node;
00637 }
00638
00639 WTreeNode *Home::makeTreeFile(const std::string name, WTreeNode *parent)
00640 {
00641 WIconPair *labelIcon
00642 = new WIconPair("icons/document.png",
00643 "icons/yellow-folder-open.png", false);
00644
00645 return new WTreeNode("<a href=\"" + name + "\" TARGET=\"_BLANK\">"
00646 + name + "</a>", labelIcon, parent);
00647 }
00648
00649 WApplication *createApplication(const WEnvironment& env)
00650 {
00651 WApplication *app = new WApplication(env);
00652
00653 app->messageResourceBundle().use("wt-home", false);
00654 app->useStyleSheet("images/wt.css");
00655 app->useStyleSheet("home.css");
00656 app->setTitle("Wt, C++ Web Toolkit");
00657
00658 new Home(app->root());
00659 return app;
00660 }
00661
00662 int main(int argc, char **argv)
00663 {
00664 return WRun(argc, argv, &createApplication);
00665 }
00666