|
#include <Wt/WApplication.h>
|
|
#include <Wt/WContainerWidget.h>
|
|
#include <Wt/WMenu.h>
|
|
#include <Wt/WStackedWidget.h>
|
|
#include <Wt/WText.h>
|
|
#include <Wt/WVBoxLayout.h>
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
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<std::string, std::string> urlParamByMask(const std::string& part, const std::string& mask)
|
|
{
|
|
std::map<std::string, std::string> result;
|
|
|
|
if (!part.empty() && !mask.empty()) {
|
|
typedef boost::split_iterator<std::string::const_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<std::string::const_iterator>(it2->begin() + 2, it2->end() - 1);
|
|
|
|
// result[param] = val
|
|
result[boost::copy_range<std::string>(range)] = boost::copy_range<std::string>(*it1);
|
|
} else {
|
|
if (*it2 != *it1) {
|
|
return std::map<std::string, std::string>();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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<Wt::WVBoxLayout>());
|
|
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<Wt::WText>("__________BEGIN OneParamWidget__________"));
|
|
|
|
std::string s;
|
|
|
|
vbox->addWidget(std::make_unique<Wt::WText>("-> one " + basePath1_));
|
|
|
|
s = app->internalPathNextPart(basePath1_);
|
|
vbox->addWidget(std::make_unique<Wt::WText>("-> param {1} gallery > " + s));
|
|
|
|
auto partUrl = urlParamByMask(internalPath, "/gallery/${gal_id}");
|
|
for (const auto& [param, part] : partUrl) {
|
|
vbox->addWidget(std::make_unique<Wt::WText>("-> urlParamByMask (param: " + param + ", part: " + part + ")"));
|
|
}
|
|
|
|
vbox->addWidget(std::make_unique<Wt::WText>("__________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<Wt::WVBoxLayout>());
|
|
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<Wt::WText>("__________BEGIN TwoParamWidget__________"));
|
|
|
|
std::string s;
|
|
vbox->addWidget(std::make_unique<Wt::WText>(" -> two " + basePath1_ + "photo/" + app->internalPathNextPart(basePath2_)));
|
|
|
|
vbox->addWidget(std::make_unique<Wt::WText>(basePath1_));
|
|
|
|
vbox->addWidget(std::make_unique<Wt::WText>(basePath2_));
|
|
|
|
s = app->internalPathNextPart(basePath1_);
|
|
vbox->addWidget(std::make_unique<Wt::WText>(" -> param {1} gallery > " + s));
|
|
|
|
if (app->internalPathMatches(basePath2_)) {
|
|
s = app->internalPathNextPart(basePath2_);
|
|
vbox->addWidget(std::make_unique<Wt::WText>(" -> 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<Wt::WText>("-> urlParamByMask (param: " + param + ", part: " + part + ")"));
|
|
}
|
|
|
|
vbox->addWidget(std::make_unique<Wt::WText>("__________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<Wt::WStackedWidget> contentWidget;
|
|
};
|
|
|
|
HelloApplication::HelloApplication(const Wt::WEnvironment& env)
|
|
: WApplication(env)
|
|
{
|
|
text_ = root()->addWidget(std::make_unique<Wt::WContainerWidget>());
|
|
text_->setMargin(12);
|
|
|
|
contentWidget = std::make_unique<Wt::WStackedWidget>();
|
|
contentWidget->setMargin(12);
|
|
|
|
auto menu = root()->addWidget(std::make_unique<Wt::WMenu>(contentWidget.get()));
|
|
menu->setInternalBasePath("/");
|
|
menu->setInternalPathEnabled("/");
|
|
|
|
// ...
|
|
{ // Add item Home on menu
|
|
auto item = menu->addItem("Home", std::make_unique<OneParamWidget>("Home page", menu->internalBasePath()), Wt::ContentLoading::Lazy);
|
|
item->setPathComponent("");
|
|
}
|
|
{ // Add item all Galleries on menu
|
|
auto item = menu->addItem("Galleries", std::make_unique<OneParamWidget>("Galleries page", menu->internalBasePath()), Wt::ContentLoading::Lazy);
|
|
item->setPathComponent("gallery");
|
|
}
|
|
// ...
|
|
{
|
|
menuGal = root()->addWidget(std::make_unique<Wt::WMenu>(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<OneParamWidget>(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<Wt::WMenu>(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<TwoParamWidget>(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<HelloApplication>(env);
|
|
});
|
|
}
|