#include #include #include #include #include #include #include class Menu : public Wt::WMenu { protected: void internalPathChanged(const std::string& path) override { // exp Wt::WMenu::internalPathChanged(path); }; }; class BaseWidget : public Wt::WContainerWidget { public: std::string s_; const static inline std::string FORWARD_SLASH = "/"; std::map urlParamByMask(const std::string& part, const std::string& mask) { std::map result; if (!part.empty() && !mask.empty()) { typedef boost::split_iterator spliterator; spliterator it1 = spliterator(part.begin() + 1, part.end(), boost::first_finder(FORWARD_SLASH, boost::is_equal())); for (spliterator it2 = spliterator(mask.begin() + 1, mask.end(), boost::first_finder(FORWARD_SLASH, boost::is_equal())); it1 != spliterator() && it2 != spliterator(); ++it1, ++it2) { // Check dynamic segment (e.g. "${var}") if (boost::starts_with(*it2, "${") && boost::ends_with(*it2, "}")) { auto range = boost::iterator_range(it2->begin() + 2, it2->end() - 1); // result[param] = val result[boost::copy_range(range)] = boost::copy_range(*it1); } else { if (*it2 != *it1) { return std::map(); } } } } return result; } }; class OneParamWidget : public BaseWidget { public: OneParamWidget(const std::string& s, const std::string& basePath1) : s_(s) , basePath1_(basePath1) { Wt::log("log") << "Create OneParamWidget" << s; vbox = this->setLayout(std::make_unique()); auto d = Wt::WCssDecorationStyle(); d.setBackgroundColor(Wt::WColor("#E2F3FF")); this->setDecorationStyle(d); handleInternalPath(Wt::WApplication::instance()->internalPath()); Wt::WApplication::instance()->internalPathChanged().connect(this, &OneParamWidget::handleInternalPath); }; std::string s_, basePath1_; Wt::WVBoxLayout* vbox = nullptr; ~OneParamWidget() {}; void handleInternalPath(const std::string& internalPath) { Wt::WApplication* app = Wt::WApplication::instance(); if (app->internalPathMatches(basePath1_)) { vbox->addWidget(std::make_unique("__________BEGIN OneParamWidget__________")); std::string s; vbox->addWidget(std::make_unique("-> one " + basePath1_)); s = app->internalPathNextPart(basePath1_); vbox->addWidget(std::make_unique("-> param {1} gallery > " + s)); auto partUrl = urlParamByMask(internalPath, "/gallery/${gal_id}"); for (const auto& [param, part] : partUrl) { vbox->addWidget(std::make_unique("-> urlParamByMask (param: " + param + ", part: " + part + ")")); } vbox->addWidget(std::make_unique("__________END OneParamWidget__________")); } } }; class TwoParamWidget : public BaseWidget { public: TwoParamWidget(const std::string& s, const std::string& basePath1, const std::string& basePath2) : s_(s) , basePath1_(basePath1) , basePath2_(basePath2) { Wt::log("log") << "Create TwoParamWidget" << s; vbox = this->setLayout(std::make_unique()); auto d = Wt::WCssDecorationStyle(); d.setBackgroundColor(Wt::WColor("#FDFFE2")); this->setDecorationStyle(d); handleInternalPath(Wt::WApplication::instance()->internalPath()); Wt::WApplication::instance()->internalPathChanged().connect(this, &TwoParamWidget::handleInternalPath); }; std::string s_, basePath1_, basePath2_; Wt::WVBoxLayout* vbox = nullptr; ~TwoParamWidget() {}; void handleInternalPath(const std::string& internalPath) { Wt::WApplication* app = Wt::WApplication::instance(); if (app->internalPathMatches(basePath2_)) { vbox->addWidget(std::make_unique("__________BEGIN TwoParamWidget__________")); std::string s; vbox->addWidget(std::make_unique(" -> two " + basePath1_ + "photo/" + app->internalPathNextPart(basePath2_))); vbox->addWidget(std::make_unique(basePath1_)); vbox->addWidget(std::make_unique(basePath2_)); s = app->internalPathNextPart(basePath1_); vbox->addWidget(std::make_unique(" -> param {1} gallery > " + s)); if (app->internalPathMatches(basePath2_)) { s = app->internalPathNextPart(basePath2_); vbox->addWidget(std::make_unique(" -> param {2} photo > " + s)); } auto partUrl = urlParamByMask(internalPath, "/gallery/${gal_id}/photo/${pho_id}"); for (const auto& [param, part] : partUrl) { vbox->addWidget(std::make_unique("-> urlParamByMask (param: " + param + ", part: " + part + ")")); } vbox->addWidget(std::make_unique("__________END TwoParamWidget__________")); } } }; class HelloApplication : public Wt::WApplication { public: HelloApplication(const Wt::WEnvironment& env); private: Wt::WLineEdit* nameEdit_; Wt::WContainerWidget* text_; Wt::WMenu *menu, *menuGal, *menuGalPhoto; std::unique_ptr contentWidget; }; HelloApplication::HelloApplication(const Wt::WEnvironment& env) : WApplication(env) { text_ = root()->addWidget(std::make_unique()); text_->setMargin(12); contentWidget = std::make_unique(); contentWidget->setMargin(12); auto menu = root()->addWidget(std::make_unique(contentWidget.get())); menu->setInternalBasePath("/"); menu->setInternalPathEnabled("/"); // ... { // Add item Home on menu auto item = menu->addItem("Home", std::make_unique("Home page", menu->internalBasePath()), Wt::ContentLoading::Lazy); item->setPathComponent(""); } { // Add item all Galleries on menu auto item = menu->addItem("Galleries", std::make_unique("Galleries page", menu->internalBasePath()), Wt::ContentLoading::Lazy); item->setPathComponent("gallery"); } // ... { menuGal = root()->addWidget(std::make_unique(contentWidget.get())); menuGal->setInternalPathEnabled("gallery"); { for (int i = 1; i <= 3; ++i) { // Add gallery in menu auto item = menuGal->addItem(Wt::WString("Gallery {1}") .arg(i), std::make_unique(Wt::WString("Gallegy {1}") .arg(i) .toUTF8(), menuGal->internalBasePath()), Wt::ContentLoading::Lazy); item->setPathComponent(Wt::WString("g{1}") .arg(i) .toUTF8()); { menuGalPhoto = root()->addWidget(std::make_unique(contentWidget.get())); menuGalPhoto->setInternalPathEnabled(menuGal->internalBasePath() + item->pathComponent() + "/photo"); { for (int j = 1; j <= 3; ++j) { // Add photos in gallery auto item1 = menuGalPhoto->addItem(Wt::WString("Photo {1} from Galley {2}") .arg(j) .arg(i), std::make_unique(Wt::WString("Photo {1} from Galley {2}") .arg(j) .arg(i) .toUTF8(), menuGal->internalBasePath(), menuGalPhoto->internalBasePath()), Wt::ContentLoading::Lazy); item1->setPathComponent(Wt::WString("p{1}") .arg(j) .toUTF8()); } } } } } } root()->addWidget(std::move(contentWidget)); } int main(int argc, char** argv) { return Wt::WRun(argc, argv, [](const Wt::WEnvironment& env) { return std::make_unique(env); }); }