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