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 <WTable>
00023 #include <WTableCell>
00024 #include <WText>
00025 #include <WTreeNode>
00026 #include <WViewWidget>
00027
00028 #include "Home.h"
00029 #include "RoundedWidget.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 Home::Home(WContainerWidget *parent)
00063 : WContainerWidget(parent)
00064 {
00065 WTable *topLayout = new WTable(this);
00066
00067 WTable *header = new WTable(topLayout->elementAt(0, 0));
00068 WImage *icon = new WImage("uiloog.jpg", header->elementAt(0, 0));
00069 icon->setMargin(WLength(15));
00070
00071 new WText("<h1>Wt: a C++ Web Toolkit</h1>", header->elementAt(0, 1));
00072 if (!wApp->environment().javaScript()) {
00073 new WText("<i>(non-javascript version)</i>",
00074 header->elementAt(0, 1));
00075 }
00076
00077 WTable *body = new WTable(topLayout->elementAt(1, 0));
00078 WStackedWidget *contents = new WStackedWidget(body->elementAt(0, 1));
00079
00080
00081
00082
00083 RoundedWidget *rounded = new RoundedWidget(RoundedWidget::All,
00084 body->elementAt(0, 0));
00085 rounded->setBackgroundColor(WColor(247,236,111));
00086 rounded->resize(WLength(18, WLength::FontEx), WLength());
00087 rounded->setMargin(WLength(15), Right);
00088
00089 WMenu *menu = new WMenu(contents, WMenu::Vertical, rounded->contents());
00090
00091 menu->setStyleClass("menu");
00092 menu->enableBrowserHistory("main");
00093
00094 body->elementAt(0, 0)->setContentAlignment(AlignTop | AlignLeft);
00095 body->elementAt(0, 1)->setContentAlignment(AlignTop | AlignLeft);
00096
00097 menu->addItem("Introduction", introduction());
00098 menu->addItem("News", deferCreate(boost::bind(&Home::news, this)),
00099 WMenuItem::PreLoading);
00100 menu->addItem("Status", wrapViewOrDefer(&Home::status),
00101 WMenuItem::PreLoading);
00102 menu->addItem("Features", wrapViewOrDefer(&Home::features),
00103 WMenuItem::PreLoading);
00104 menu->addItem("Documentation", wrapViewOrDefer(&Home::documentation),
00105 WMenuItem::PreLoading);
00106 menu->addItem("Examples", examples(), WMenuItem::PreLoading);
00107 menu->addItem("Download", deferCreate(boost::bind(&Home::download, this)),
00108 WMenuItem::PreLoading);
00109 menu->addItem("Community", wrapViewOrDefer(&Home::community),
00110 WMenuItem::PreLoading);
00111
00112 changeTitle(menu->currentItem());
00113
00114 menu->itemSelected.connect(SLOT(this, Home::changeTitle));
00115 }
00116
00117 void Home::changeTitle(WMenuItem *item)
00118 {
00119 wApp->setTitle(L"Wt, C++ Web Toolkit - " + item->text().value());
00120 }
00121
00122 WWidget *Home::introduction()
00123 {
00124 return new WText(tr("home.intro"));
00125 }
00126
00127 void Home::refresh()
00128 {
00129 readNews(recentNews_, "latest-news.txt");
00130 readNews(historicalNews_, "historical-news.txt");
00131 readReleases(releases_, "releases.txt");
00132
00133 WContainerWidget::refresh();
00134 }
00135
00136 WWidget *Home::news()
00137 {
00138 WContainerWidget *result = new WContainerWidget();
00139
00140 result->addWidget(new WText("<h2><span>Latest News</span></h2>"));
00141 recentNews_ = new WTable();
00142 readNews(recentNews_, "latest-news.txt");
00143 result->addWidget(recentNews_);
00144
00145 result->addWidget(new WText("<h2><span>Historical News</span></h2>"));
00146 historicalNews_ = new WTable();
00147 readNews(historicalNews_, "historical-news.txt");
00148 result->addWidget(historicalNews_);
00149
00150 return result;
00151 }
00152
00153 WWidget *Home::status()
00154 {
00155 return new WText(tr("home.status"));
00156 }
00157
00158 WWidget *Home::features()
00159 {
00160 return new WText(tr("home.features"));
00161 }
00162
00163 WWidget *Home::documentation()
00164 {
00165 return new WText(tr("home.documentation"));
00166 }
00167
00168 WWidget *Home::helloWorldExample()
00169 {
00170 WContainerWidget *result = new WContainerWidget();
00171
00172 new WText(tr("home.examples.hello"), result);
00173
00174 WTreeNode *tree = makeTreeMap("Hello world", 0);
00175 makeTreeFile("hello.C", tree);
00176
00177 tree->expand();
00178
00179 result->addWidget(tree);
00180
00181 return result;
00182 }
00183
00184 WWidget *Home::homepageExample()
00185 {
00186 WContainerWidget *result = new WContainerWidget();
00187
00188 new WText(tr("home.examples.wt"), result);
00189
00190 WTreeNode *tree = makeTreeMap("Wt Homepage", 0);
00191 WTreeNode *home = makeTreeMap("class Home", tree);
00192 makeTreeFile("Home.h", home);
00193 makeTreeFile("Home.C", home);
00194 WTreeNode *treeexample = makeTreeMap("class TreeListExample", tree);
00195 makeTreeFile("TreeListExample.h", treeexample);
00196 makeTreeFile("TreeListExample.C", treeexample);
00197 makeTreeFile("wt-home.xml", tree);
00198
00199 tree->expand();
00200
00201 result->addWidget(tree);
00202
00203 return result;
00204 }
00205
00206 WWidget *Home::formExample()
00207 {
00208 WContainerWidget *result = new WContainerWidget();
00209
00210 new WText(tr("home.examples.form"), result);
00211
00212 WTreeNode *tree = makeTreeMap("Form example", 0);
00213 WTreeNode *form = makeTreeMap("class Form", tree);
00214 makeTreeFile("Form.h", form);
00215 makeTreeFile("Form.C", form);
00216 WTreeNode *formexample = makeTreeMap("class FormExample", tree);
00217 makeTreeFile("FormExample.h", formexample);
00218 makeTreeFile("FormExample.C", formexample);
00219 WTreeNode *datevalidator = makeTreeMap("class DateValidator", tree);
00220 makeTreeFile("DateValidator.h", datevalidator);
00221 makeTreeFile("DateValidator.C", datevalidator);
00222 makeTreeFile("form-example.xml", tree);
00223 makeTreeFile("form-example_nl.xml", tree);
00224
00225 tree->expand();
00226
00227 result->addWidget(tree);
00228
00229 return result;
00230 }
00231
00232 WWidget *Home::treelistExample()
00233 {
00234 WContainerWidget *result = new WContainerWidget();
00235
00236 new WText(tr("home.examples.treelist"), result);
00237 new TreeListExample(result);
00238 new WText(tr("home.examples.treelist-remarks"), result);
00239
00240 return result;
00241 }
00242
00243 WWidget *Home::hangmanExample()
00244 {
00245 WContainerWidget *result = new WContainerWidget();
00246
00247 new WText(tr("home.examples.hangman"), result);
00248
00249 WTreeNode *tree = makeTreeMap("Hangman game", 0);
00250 tree->setLoadPolicy(WTreeNode::PreLoading);
00251
00252 WTreeNode *widgets = makeTreeMap("Widgets", tree);
00253 WTreeNode *loginwidget = makeTreeMap("class LoginWidget", widgets);
00254 makeTreeFile("LoginWidget.h", loginwidget);
00255 makeTreeFile("LoginWidget.C", loginwidget);
00256 WTreeNode *hangmanwidget = makeTreeMap("class HangmanWidget", widgets);
00257 makeTreeFile("HangmanWidget.h", hangmanwidget);
00258 makeTreeFile("HangmanWidget.C", hangmanwidget);
00259 WTreeNode *highscoreswidget = makeTreeMap("class HighScoresWidget", widgets);
00260 makeTreeFile("HighScoresWidget.h", highscoreswidget);
00261 makeTreeFile("HighScoresWidget.C", highscoreswidget);
00262 WTreeNode *hangmangame = makeTreeMap("class HangmanGame", widgets);
00263 makeTreeFile("HangmanGame.h", hangmangame);
00264 makeTreeFile("HangmanGame.C", hangmangame);
00265 WTreeNode *other = makeTreeMap("Other", tree);
00266 WTreeNode *hangmandb = makeTreeMap("class HangmanDb", other);
00267 makeTreeFile("HangmanDb.h", hangmandb);
00268 makeTreeFile("HangmanDb.C", hangmandb);
00269 WTreeNode *dictionary = makeTreeMap("class Dictionary", other);
00270 makeTreeFile("Dictionary.h", dictionary);
00271 makeTreeFile("Dictionary.C", dictionary);
00272 makeTreeFile("hangman.C", other);
00273
00274 tree->expand();
00275
00276 result->addWidget(tree);
00277
00278 return result;
00279 }
00280
00281 WWidget *Home::styleExample()
00282 {
00283 WContainerWidget *result = new WContainerWidget();
00284
00285 new WText(tr("home.examples.style"), result);
00286
00287 WTreeNode *tree = makeTreeMap("Style example", 0);
00288 WTreeNode *cornerimage = makeTreeMap("class CornerImage", tree);
00289 makeTreeFile("CornerImage.h", cornerimage);
00290 makeTreeFile("CornerImage.C", cornerimage);
00291 WTreeNode *roundedwidget = makeTreeMap("class RoundedWidget", tree);
00292 makeTreeFile("RoundedWidget.h", roundedwidget);
00293 makeTreeFile("RoundedWidget.C", roundedwidget);
00294 WTreeNode *styleexample = makeTreeMap("class StyleExample", tree);
00295 makeTreeFile("StyleExample.h", styleexample);
00296 makeTreeFile("StyleExample.C", styleexample);
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::fileExplorerExample()
00373 {
00374 WContainerWidget *result = new WContainerWidget();
00375
00376 new WText(tr("home.examples.fileexplorer"), result);
00377
00378 WTreeNode *tree = makeTreeMap("File explorer example", 0);
00379
00380 WTreeNode *classMap;
00381 classMap = makeTreeMap("class FileTreeTableNode", tree);
00382 makeTreeFile("FileTreeTableNode.h", classMap);
00383 makeTreeFile("FileTreeTableNode.C", classMap);
00384 classMap = makeTreeMap("class FileTreeTable", tree);
00385 makeTreeFile("FileTreeTable.h", classMap);
00386 makeTreeFile("FileTreeTable.C", classMap);
00387 makeTreeFile("FileTreeExample.C", tree);
00388 makeTreeFile("filetree.css", tree);
00389
00390 tree->expand();
00391
00392 result->addWidget(tree);
00393
00394 return result;
00395 }
00396
00397 WWidget *Home::calendarExample()
00398 {
00399 WContainerWidget *result = new WContainerWidget();
00400
00401 new WText(tr("home.examples.calendar"), result);
00402
00403 new WText("<p>A field for editing a date in conjunction "
00404 "with a WDatePicker:</p>", result);
00405
00406 WTable *tab = new WTable(result);
00407 new WText("Please enter your birth date: ", tab->elementAt(0, 0));
00408 WLineEdit *dateEdit = new WLineEdit(tab->elementAt(0, 1));
00409 dateEdit->setMargin(WLength(5), Right);
00410
00411 WDatePicker *picker = new WDatePicker(new WPushButton("..."), dateEdit,
00412 false, tab->elementAt(0, 1));
00413 tab->elementAt(0, 0)->setPadding(WLength(8));
00414 tab->elementAt(0, 1)->setPadding(WLength(8));
00415
00416 new WText("<p>A plain calendar:</p>", result);
00417 WCalendar *cal = new WCalendar(false, result);
00418 cal->setMargin(WLength(8));
00419
00420 new WText("<p>A calendar with multiple selection:</p>", result);
00421 cal = new WCalendar(false, result);
00422 cal->setMultipleSelection(true);
00423 cal->setMargin(WLength(8));
00424
00425
00426 return result;
00427 }
00428
00429 WWidget *Home::wrapViewOrDefer(WWidget *(Home::*createWidget)())
00430 {
00431
00432
00433
00434
00435
00436
00437
00438 if (wApp->environment().javaScript())
00439 return makeStaticModel(boost::bind(createWidget, this));
00440 else
00441 return deferCreate(boost::bind(createWidget, this));
00442 }
00443
00444 WWidget *Home::examples()
00445 {
00446 WContainerWidget *result = new WContainerWidget();
00447
00448 result->addWidget(new WText(tr("home.examples")));
00449
00450 WStackedWidget *exampleStack = new WStackedWidget();
00451
00452
00453
00454
00455 RoundedWidget *rounded = new RoundedWidget(RoundedWidget::All, result);
00456 rounded->setBackgroundColor(WColor(0xE0,0xE8,0xFF));
00457
00458 WMenu *exampleMenu = new WMenu(exampleStack, WMenu::Horizontal,
00459 rounded->contents());
00460 exampleMenu->setStyleClass("menu");
00461 exampleMenu->enableBrowserHistory("example");
00462
00463 result->addWidget(exampleStack);
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 exampleMenu->addItem("Hello world",
00483 wrapViewOrDefer(&Home::helloWorldExample));
00484 exampleMenu->addItem("Form",
00485 wrapViewOrDefer(&Home::formExample));
00486 exampleMenu->addItem("Wt homepage",
00487 wrapViewOrDefer(&Home::homepageExample));
00488 exampleMenu->addItem("Treelist",
00489 deferCreate(boost::bind(&Home::treelistExample, this)));
00490 exampleMenu->addItem("Hangman",
00491 wrapViewOrDefer(&Home::hangmanExample));
00492 exampleMenu->addItem("Style",
00493 wrapViewOrDefer(&Home::styleExample));
00494 exampleMenu->addItem("Mail composer",
00495 wrapViewOrDefer(&Home::composerExample));
00496 exampleMenu->addItem("Drag & Drop",
00497 wrapViewOrDefer(&Home::dragdropExample));
00498 exampleMenu->addItem("File explorer",
00499 wrapViewOrDefer(&Home::fileExplorerExample));
00500 exampleMenu->addItem("Calendar",
00501 deferCreate(boost::bind(&Home::calendarExample, this)));
00502
00503 return result;
00504 }
00505
00506 WWidget *Home::download()
00507 {
00508 WContainerWidget *result = new WContainerWidget();
00509 result->addWidget(new WText("<h2><span>Download</span></h2>"));
00510 result->addWidget(new WText(tr("home.download.license")));
00511 result->addWidget(new WText(tr("home.download.requirements")));
00512 result->addWidget(new WText("<h3>Available packages</h3>"));
00513
00514 releases_ = new WTable();
00515 readReleases(releases_, "releases.txt");
00516 result->addWidget(releases_);
00517
00518 result->addWidget
00519 (new WText("<p>Older releases are still available at "
00520 + href("http://sourceforge.net/project/showfiles.php?"
00521 "group_id=153710#files",
00522 "sourceforge.net")
00523 + "</p>"));
00524
00525 return result;
00526 }
00527
00528 std::string Home::href(const std::string url, const std::string description)
00529 {
00530 return "<a href=\"" + url + "\" TARGET=\"_blank\">" + description + "</a>";
00531 }
00532
00533 WWidget *Home::community()
00534 {
00535 return new WText(tr("home.community"));
00536 }
00537
00538 void Home::readNews(WTable *newsTable, const std::string newsfile)
00539 {
00540 std::ifstream f(newsfile.c_str());
00541
00542 newsTable->clear();
00543
00544 int row = 0;
00545
00546 while (f) {
00547 std::string line;
00548 getline(f, line);
00549
00550 if (f) {
00551 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00552 CsvTokenizer;
00553 CsvTokenizer tok(line);
00554
00555 CsvTokenizer::iterator i=tok.begin();
00556
00557 newsTable->elementAt(row, 0)->
00558 addWidget(new WText("<p><b>" + *i + "</b></p>"));
00559 newsTable->elementAt(row, 0)
00560 ->setContentAlignment(AlignCenter | AlignTop);
00561 newsTable->elementAt(row, 0)
00562 ->resize(WLength(16, WLength::FontEx), WLength());
00563 newsTable
00564 ->elementAt(row, 1)->addWidget(new WText("<p>" + *(++i) + "</p>"));
00565
00566 ++row;
00567 }
00568 }
00569 }
00570
00571 void Home::readReleases(WTable *releaseTable, const std::string releasefile)
00572 {
00573 std::ifstream f(releasefile.c_str());
00574
00575 releaseTable->clear();
00576
00577 releaseTable->elementAt(0, 0)->addWidget(new WText("<b>Version</b>"));
00578 releaseTable->elementAt(0, 1)->addWidget(new WText("<b>Date</b>"));
00579 releaseTable->elementAt(0, 2)->addWidget(new WText("<b>Description</b>"));
00580
00581 releaseTable->elementAt(0, 0)->resize(WLength(10, WLength::FontEx),
00582 WLength());
00583 releaseTable->elementAt(0, 1)->resize(WLength(15, WLength::FontEx),
00584 WLength());
00585
00586 int row = 1;
00587
00588 while (f) {
00589 std::string line;
00590 getline(f, line);
00591
00592 if (f) {
00593 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00594 CsvTokenizer;
00595 CsvTokenizer tok(line);
00596
00597 CsvTokenizer::iterator i=tok.begin();
00598
00599 std::string version = *i;
00600 releaseTable->elementAt(row, 0)->addWidget
00601 (new WText(href("http://prdownloads.sourceforge.net/witty/wt-"
00602 + version + ".tar.gz?download", "Wt " + version)));
00603 releaseTable->elementAt(row, 1)->addWidget(new WText(*(++i)));
00604 releaseTable->elementAt(row, 2)->addWidget(new WText(*(++i)));
00605
00606 ++row;
00607 }
00608 }
00609 }
00610
00611 WTreeNode *Home::makeTreeMap(const std::string name, WTreeNode *parent)
00612 {
00613 WIconPair *labelIcon
00614 = new WIconPair("icons/yellow-folder-closed.png",
00615 "icons/yellow-folder-open.png", false);
00616
00617 WTreeNode *node = new WTreeNode(name, labelIcon, parent);
00618 node->label()->setFormatting(WText::PlainFormatting);
00619
00620 if (!parent) {
00621 node->setImagePack("icons/");
00622 node->expand();
00623 node->setLoadPolicy(WTreeNode::NextLevelLoading);
00624 }
00625
00626 return node;
00627 }
00628
00629 WTreeNode *Home::makeTreeFile(const std::string name, WTreeNode *parent)
00630 {
00631 WIconPair *labelIcon
00632 = new WIconPair("icons/document.png",
00633 "icons/yellow-folder-open.png", false);
00634
00635 return new WTreeNode("<a href=\"" + name + "\" TARGET=\"_BLANK\">"
00636 + name + "</a>", labelIcon, parent);
00637 }
00638
00639 WApplication *createApplication(const WEnvironment& env)
00640 {
00641 WApplication *app = new WApplication(env);
00642
00643 app->messageResourceBundle().use("wt-home", false);
00644 app->useStyleSheet("home.css");
00645 app->setTitle("Wt, C++ Web Toolkit");
00646
00647 new Home(app->root());
00648 return app;
00649 }
00650
00651 int main(int argc, char **argv)
00652 {
00653 return WRun(argc, argv, &createApplication);
00654 }
00655