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 #include <boost/algorithm/string.hpp>
00013
00014 #include <Wt/WAnchor>
00015 #include <Wt/WApplication>
00016 #include <Wt/WEnvironment>
00017 #include <Wt/WIconPair>
00018 #include <Wt/WImage>
00019 #include <Wt/WLineEdit>
00020 #include <Wt/WLogger>
00021 #include <Wt/WMenu>
00022 #include <Wt/WPushButton>
00023 #include <Wt/WStackedWidget>
00024 #include <Wt/WVBoxLayout>
00025 #include <Wt/WTabWidget>
00026 #include <Wt/WTable>
00027 #include <Wt/WTableCell>
00028 #include <Wt/WText>
00029 #include <Wt/WViewWidget>
00030
00031 #include "Home.h"
00032
00033 static const std::string SRC_INTERNAL_PATH = "src";
00034
00035
00036 class Div : public WContainerWidget
00037 {
00038 public:
00039 Div(WContainerWidget *parent, const std::string& id)
00040 : WContainerWidget(parent)
00041 {
00042 setId(id);
00043 }
00044 };
00045
00046 Home::~Home()
00047 {
00048 }
00049
00050 Home::Home(const WEnvironment& env, const std::string& title,
00051 const std::string& resourceBundle, const std::string& cssPath)
00052 : WApplication(env),
00053 recentNews_(0),
00054 historicalNews_(0),
00055 releases_(0),
00056 homePage_(0),
00057 sourceViewer_(0)
00058 {
00059 messageResourceBundle().use(resourceBundle, false);
00060 useStyleSheet(cssPath + "/wt.css");
00061 useStyleSheet(cssPath + "/wt_ie.css", "lt IE 7");
00062 useStyleSheet("home.css");
00063 useStyleSheet("sourceview.css");
00064 setTitle(title);
00065
00066 setLocale("");
00067 language_ = 0;
00068 }
00069
00070 void Home::init()
00071 {
00072 internalPathChanged().connect(SLOT(this, Home::setup));
00073 internalPathChanged().connect(SLOT(this, Home::setLanguageFromPath));
00074 internalPathChanged().connect(SLOT(this, Home::logInternalPath));
00075
00076 setup();
00077 }
00078
00079 void Home::setup()
00080 {
00081
00082
00083
00084
00085
00086
00087 std::string base = internalPathNextPart("/");
00088
00089 if (base == SRC_INTERNAL_PATH) {
00090 if (!sourceViewer_) {
00091 delete homePage_;
00092 homePage_ = 0;
00093
00094 root()->clear();
00095
00096 sourceViewer_ = sourceViewer("/" + SRC_INTERNAL_PATH + "/");
00097 WVBoxLayout *layout = new WVBoxLayout();
00098 layout->setContentsMargins(0, 0, 0, 0);
00099 layout->addWidget(sourceViewer_);
00100 root()->setLayout(layout);
00101 }
00102 } else {
00103 if (!homePage_) {
00104 delete sourceViewer_;
00105 sourceViewer_ = 0;
00106
00107 root()->clear();
00108
00109 homePage_ = initHome();
00110 root()->addWidget(homePage_);
00111 }
00112 }
00113 }
00114
00115 WWidget *Home::initHome()
00116 {
00117 WContainerWidget *result = new WContainerWidget(root());
00118 Div *topWrapper = new Div(result, "top_wrapper");
00119 Div *topContent = new Div(topWrapper, "top_content");
00120
00121 Div *languagesDiv = new Div(topContent, "top_languages");
00122
00123 for (unsigned i = 0; i < languages.size(); ++i) {
00124 if (i != 0)
00125 new WText("- ", languagesDiv);
00126
00127 const Lang& l = languages[i];
00128
00129 WAnchor *a = new WAnchor("", l.longDescription_, languagesDiv);
00130 a->setRefInternalPath(l.path_);
00131 }
00132
00133 WText *topWt = new WText(tr("top_wt"), topContent);
00134 topWt->setInline(false);
00135 topWt->setId("top_wt");
00136
00137 WText *bannerWt = new WText(tr("banner_wrapper"), result);
00138 bannerWt->setId("banner_wrapper");
00139
00140 Div *mainWrapper = new Div(result, "main_wrapper");
00141 Div *mainContent = new Div(mainWrapper, "main_content");
00142 Div *mainMenu = new Div(mainContent, "main_menu");
00143
00144 WStackedWidget *contents = new WStackedWidget();
00145 contents->setId("main_page");
00146
00147 mainMenu_ = new WMenu(contents, Vertical, mainMenu);
00148 mainMenu_->setRenderAsList(true);
00149
00150 mainMenu_->addItem
00151 (tr("introduction"), introduction())->setPathComponent("");
00152
00153 mainMenu_->addItem
00154 (tr("news"), deferCreate(boost::bind(&Home::news, this)),
00155 WMenuItem::PreLoading);
00156
00157 mainMenu_->addItem
00158 (tr("features"), wrapView(&Home::features), WMenuItem::PreLoading);
00159
00160 mainMenu_->addItem
00161 (tr("documentation"), wrapView(&Home::documentation),
00162 WMenuItem::PreLoading);
00163
00164 mainMenu_->addItem
00165 (tr("examples"), examples(),
00166 WMenuItem::PreLoading)->setPathComponent("examples/");
00167
00168 mainMenu_->addItem
00169 (tr("download"), deferCreate(boost::bind(&Home::download, this)),
00170 WMenuItem::PreLoading);
00171
00172 mainMenu_->addItem
00173 (tr("community"), wrapView(&Home::community), WMenuItem::PreLoading);
00174
00175 mainMenu_->addItem
00176 (tr("other-language"), wrapView(&Home::otherLanguage),
00177 WMenuItem::PreLoading);
00178
00179 mainMenu_->itemSelectRendered().connect(SLOT(this, Home::updateTitle));
00180 mainMenu_->select((int)0);
00181
00182
00183 mainMenu_->setInternalPathEnabled("/");
00184
00185 sideBarContent_ = new WContainerWidget(mainMenu);
00186
00187 mainContent->addWidget(contents);
00188 WContainerWidget *clearAll = new WContainerWidget(mainContent);
00189 clearAll->setStyleClass("clearall");
00190
00191 WText *footerWrapper = new WText(tr("footer_wrapper"), result);
00192 footerWrapper->setId("footer_wrapper");
00193
00194 return result;
00195 }
00196
00197 void Home::setLanguage(int index)
00198 {
00199 if (homePage_) {
00200 const Lang& l = languages[index];
00201
00202 setLocale(l.code_);
00203
00204 std::string langPath = l.path_;
00205 mainMenu_->setInternalBasePath(langPath);
00206 examplesMenu_->setInternalBasePath(langPath + "examples");
00207 updateTitle();
00208
00209 language_ = index;
00210 }
00211 }
00212
00213 WWidget *Home::linkSourceBrowser(const std::string& example)
00214 {
00215 WAnchor *a = new WAnchor("", tr("source-browser"));
00216 a->setRefInternalPath("/" + SRC_INTERNAL_PATH + "/" + example);
00217 return a;
00218 }
00219
00220 void Home::setLanguageFromPath()
00221 {
00222 std::string langPath = internalPathNextPart("/");
00223
00224 if (langPath.empty())
00225 langPath = '/';
00226 else
00227 langPath = '/' + langPath + '/';
00228
00229 int newLanguage = 0;
00230
00231 for (unsigned i = 0; i < languages.size(); ++i) {
00232 if (languages[i].path_ == langPath) {
00233 newLanguage = i;
00234 break;
00235 }
00236 }
00237
00238 if (newLanguage != language_)
00239 setLanguage(newLanguage);
00240 }
00241
00242 void Home::updateTitle()
00243 {
00244 if (mainMenu_->currentItem())
00245 setTitle(tr("wt") + " - " + mainMenu_->currentItem()->text());
00246 }
00247
00248 void Home::logInternalPath(const std::string& path)
00249 {
00250
00251 log("path") << path;
00252 }
00253
00254 WWidget *Home::introduction()
00255 {
00256 return new WText(tr("home.intro"));
00257 }
00258
00259 WWidget *Home::news()
00260 {
00261 WContainerWidget *result = new WContainerWidget();
00262
00263 result->addWidget(new WText(tr("home.news")));
00264
00265 result->addWidget(new WText(tr("home.latest-news")));
00266 recentNews_ = new WTable();
00267 readNews(recentNews_, filePrefix() + "latest-news.txt");
00268 result->addWidget(recentNews_);
00269
00270 result->addWidget(new WText(tr("home.historical-news")));
00271 historicalNews_ = new WTable();
00272 readNews(historicalNews_, filePrefix() + "historical-news.txt");
00273 result->addWidget(historicalNews_);
00274
00275 return result;
00276 }
00277
00278 WWidget *Home::status()
00279 {
00280 return new WText(tr("home.status"));
00281 }
00282
00283 WWidget *Home::features()
00284 {
00285 return new WText(tr("home.features"));
00286 }
00287
00288 WWidget *Home::documentation()
00289 {
00290 return new WText(tr("home.documentation"));
00291 }
00292
00293 WWidget *Home::otherLanguage()
00294 {
00295 return new WText(tr("home.other-language"));
00296 }
00297
00298 WWidget *Home::wrapView(WWidget *(Home::*createWidget)())
00299 {
00300 return makeStaticModel(boost::bind(createWidget, this));
00301 }
00302
00303 std::string Home::href(const std::string& url, const std::string& description)
00304 {
00305 return "<a href=\"" + url + "\" target=\"_blank\">" + description + "</a>";
00306 }
00307
00308 WWidget *Home::community()
00309 {
00310 return new WText(tr("home.community"));
00311 }
00312
00313 void Home::readNews(WTable *newsTable, const std::string& newsfile)
00314 {
00315 std::ifstream f(newsfile.c_str());
00316
00317 newsTable->clear();
00318
00319 int row = 0;
00320
00321 while (f) {
00322 std::string line;
00323 getline(f, line);
00324
00325 if (f) {
00326 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00327 CsvTokenizer;
00328 CsvTokenizer tok(line);
00329
00330 CsvTokenizer::iterator i=tok.begin();
00331
00332 newsTable->elementAt(row, 0)->
00333 addWidget(new WText("<p><b>" + *i + "</b></p>"));
00334 newsTable->elementAt(row, 0)
00335 ->setContentAlignment(AlignCenter | AlignTop);
00336 newsTable->elementAt(row, 0)
00337 ->resize(WLength(16, WLength::FontEx), WLength::Auto);
00338 newsTable
00339 ->elementAt(row, 1)->addWidget(new WText("<p>" + *(++i) + "</p>"));
00340
00341 ++row;
00342 }
00343 }
00344 }
00345
00346 void Home::readReleases(WTable *releaseTable)
00347 {
00348 std::ifstream f((filePrefix() + "releases.txt").c_str());
00349
00350 releaseTable->clear();
00351
00352 releaseTable->elementAt(0, 0)
00353 ->addWidget(new WText(tr("home.download.version")));
00354 releaseTable->elementAt(0, 1)
00355 ->addWidget(new WText(tr("home.download.date")));
00356 releaseTable->elementAt(0, 2)
00357 ->addWidget(new WText(tr("home.download.description")));
00358
00359 releaseTable->elementAt(0, 0)->resize(WLength(15, WLength::FontEx),
00360 WLength::Auto);
00361 releaseTable->elementAt(0, 1)->resize(WLength(15, WLength::FontEx),
00362 WLength::Auto);
00363
00364 int row = 1;
00365
00366 while (f) {
00367 std::string line;
00368 getline(f, line);
00369
00370 if (f) {
00371 typedef boost::tokenizer<boost::escaped_list_separator<char> >
00372 CsvTokenizer;
00373 CsvTokenizer tok(line);
00374
00375 CsvTokenizer::iterator i=tok.begin();
00376
00377 std::string fileName = *i;
00378 std::string description = *(++i);
00379 releaseTable->elementAt(row, 0)->addWidget
00380 (new WText(href("http://prdownloads.sourceforge.net/witty/"
00381 + fileName + "?download", description)));
00382 releaseTable->elementAt(row, 1)->addWidget(new WText(*(++i)));
00383 releaseTable->elementAt(row, 2)->addWidget(new WText(*(++i)));
00384
00385 ++row;
00386 }
00387 }
00388 }
00389
00390 WString Home::tr(const char *key)
00391 {
00392 return WString::tr(key);
00393 }