I am very hard headed and not understanding what you are saying I should
do, so I created a small example an attached it.
Changing the combo boxes works, and changing the path manually in the
address bar works (content changes), the function gets called in
internalPathChanged, but content does not change when using combo boxes.

Thanks for being patent with me, but I am not getting this concept, it
seems it needs to be bound to stack but I do not know how to do this, it
seems if I can override the menu's page cache function it would do this
automatically, without any code.

On Thu, 2014-02-27 at 11:18 +0400, Dmitriy Igrishin wrote:
> Hey Jeffrey,
> 
> 
> 
> 
> 2014-02-27 8:52 GMT+04:00 Jeffrey Scott Flesher Gmail
> <jeffrey.scott.fles...@gmail.com>:
> 
>         setCurrentVideo() here is intended to replace the video in the
>         widget that 
>         created by WWidget* Home::video() of your code. 
>         
>         
>         
>         I got the function working using the logInternalPath change,
>         but do not see the difference between creating a new function
>         called setCurrentVideo, or just calling video again, besides
>         the binding...
>         
> Home::video() in your case should be considered just as constructor of
> the widget
> which is intended to show videos (i.e. has a video player), right? And
> this
> widget should be considered as a *page*, since it has an internal
> path.
> Note, that Home::video() *does not* adds this widget (page) into the
> widget hierarchy.
> Its will be done by WMenu::addItem() (actually, it will add this page
> into WStackedWidget,
> if you pass it in the WMenu's constructor).
> Next, the WMenu handles internal path change and if the internal path
> matches to "/video",
> then WMenu selects the corresponding item - "video" and sets the
> widget constructed by
> Home::video() as the current widget of WStackedWidget which is owned
> by WMenu.
> As far as I understood, you want to show the video which corresponds
> the URL
> (internal path), right? Then you need to write your own internal path
> changed signal
> handler (which I've posted in the previous post) since the WMenu knows
> nothing about
> the widget created by Home::video().
> Suggested setCurrentVideo() - is just for clearly understanding how
> the internal path change
> handles.
> 
> 
> 
> -- 
> // Dmitriy.
> 
> 
> 
> ------------------------------------------------------------------------------
> Flow-based real-time traffic analytics software. Cisco certified tool.
> Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer
> Customize your own dashboards, set traffic alerts and generate reports.
> Network behavioral analysis & security monitoring. All-in-one tool.
> http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk
> _______________________________________________
> witty-interest mailing list
> witty-interest@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/witty-interest
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
#include <Wt/WApplication>
#include <Wt/WMenu>
#include <Wt/WMenuItem>
#include <Wt/WPopupMenu>
#include <Wt/WStackedWidget>
#include <Wt/WText>
#include <Wt/WBootstrapTheme>
#include <Wt/WTemplate>
#include <Wt/WNavigationBar>
#include <Wt/WComboBox>
#include <Wt/WVideo>
#include <Wt/WImage>
#include <Wt/WLineEdit>
/* ****************************************************************************
 * DeferredWidget
 * A utility container widget which defers creation of its single
 * child widget until the container is loaded (which is done on-demand by a WMenu).
 * The constructor takes the create function for the widget as a parameter.
 *
 * We use this to defer widget creation until needed.
 */
template <typename Function>
class DeferredWidget : public Wt::WContainerWidget
{
    public:
        DeferredWidget(Function f) : f_(f) { }

    private:
        void load()
        {
            Wt::WContainerWidget::load();
            if (count() == 0)
            {
                addWidget(f_());
            }
        }

        Function f_;
};
/* ****************************************************************************
 * deferCreate
 */
template <typename Function>
DeferredWidget<Function> *deferCreate(Function f)
{
    return new DeferredWidget<Function>(f);
}
/* ****************************************************************************
 * Lang
 */
struct Lang
{
        Lang(const std::string& code, const std::string& path, const std::string& shortDescription, const std::string& longDescription) : code_(code), path_(path), shortDescription_(shortDescription), longDescription_(longDescription) { }
        std::string code_, path_, shortDescription_, longDescription_;
};
/* ****************************************************************************
 * App
 */
class App : public Wt::WApplication
{
    public:
        App(const Wt::WEnvironment& e);
    protected:
        Wt::WString tr(const char *key);
        void addLanguage(const Lang& l) { languages.push_back(l); }
    private:
        Wt::WWidget *homePage_;
        void create_menu();
        Wt::WWidget *Statically();
        Wt::WWidget *Dynamically();
        void logInternalPath(const std::string& path);
        std::vector<Lang> languages;
        void categoryComboChanged();
        void messageComboChanged();
        Wt::WComboBox *categoryCombo;
        Wt::WComboBox *messageCombo;
        bool isComboBoxInit=false;
        bool bindVideo = false;
        bool isChanged=false;
        void handlePopup(int data);
};
/* ****************************************************************************
 * App Contructor
 */
App::App(const Wt::WEnvironment& e) : Wt::WApplication(e)
{
    messageResourceBundle().use(appRoot() + "dynamic-menu", false);
    setTheme(new Wt::WBootstrapTheme());
    internalPathChanged().connect(this, &App::logInternalPath);
    addLanguage(Lang("en", "/", "en", "English"));
    addLanguage(Lang("cn", "/cn/", "汉语", "中文 (Chinese)"));
    addLanguage(Lang("ru", "/ru/", "ру", "Русский (Russian)"));
    create_menu();
}
/* ****************************************************************************
 * create_menu
 */
void App::create_menu()
{
    Wt::WTemplate *result = new Wt::WTemplate(tr("template"), root()); //  <message id="template">
    homePage_ = result;
    //
    Wt::WStackedWidget *contents = new Wt::WStackedWidget();
    Wt::WAnimation fade(Wt::WAnimation::Fade, Wt::WAnimation::Linear, 250);
    contents->setTransitionAnimation(fade);
    contents->setId("main_page");
    // Create a navigation bar with a link to a web page.
    Wt::WNavigationBar *navigation = new Wt::WNavigationBar(contents);
    navigation->setTitle("Witty Wizard");

    Wt::WStackedWidget *contentsStack = new Wt::WStackedWidget(contents);
    //contentsStack->setId("contents");
    contentsStack->addStyleClass("contents");

    // Setup a Main menu.
    Wt::WMenu *mainMenu_ = new Wt::WMenu(contentsStack, contents);
    mainMenu_->setId("mainmenu");
    navigation->addMenu(mainMenu_);
    // Add two menu items for example
    mainMenu_->addItem(tr("static"),  Statically())->setPathComponent("");
    mainMenu_->addItem(tr("dynamic"),  deferCreate(boost::bind(&App::Dynamically, this)));

    // Setup a Popup menu.
    Wt::WMenu *popupMenu = new Wt::WMenu();
    //popupMenu->setId("popupMenu");
    navigation->addMenu(popupMenu, Wt::AlignRight);

    // Create a popup submenu for the Help menu.
    Wt::WPopupMenu *popup = new Wt::WPopupMenu();
    popup->setId("languages");
    for (unsigned i = 0; i < languages.size(); ++i)
    {
        // Get Languages
        const Lang& l = languages[i];
        // Add Popup Item with Description.
        popup->addItem(Wt::WString::fromUTF8(l.longDescription_));
        // How do you bind this to change language?
        // Triggered - triggers all events, not just the one menu item
        popup->triggered().connect(boost::bind(&App::handlePopup, this, i));
    }

    Wt::WMenuItem *item = new Wt::WMenuItem("Language");
    item->setId("Language");
    item->setMenu(popup);
    popupMenu->addItem(item);

    /*
    // Add a Search control.
    Wt::WText *searchResult = new Wt::WText("Search");
    Wt::WLineEdit *edit = new Wt::WLineEdit();
    edit->setEmptyText("Enter a search item");
    edit->enterPressed().connect(std::bind([=] ()
    {
        mainMenu_->select(4); // is the index of the "Sales"
        searchResult->setText(Wt::WString("Nothing found for {1}.").arg(edit->text()));
    }));
    navigation->addSearch(edit, Wt::AlignRight);
    */

    contents->addWidget(contentsStack);

    // Make the menu is internal-path aware.
    mainMenu_->setInternalPathEnabled("/");
    // Bind to Template
    result->bindWidget("menu", navigation);
    result->bindWidget("contents", contents);
}
/* ****************************************************************************
 * Statically
 */
Wt::WWidget *App::Statically()
{
    return new Wt::WText(tr("static.intro"));
}
/* ****************************************************************************
 * Dynamically based on Comoboxes
 */
Wt::WWidget *App::Dynamically()
{
    Wt::log("notice") << "( *** run function Dynamically *** " << ")";
    std::string message_ = "default-0";
    Wt::WContainerWidget *result = new Wt::WContainerWidget();

    if (!isComboBoxInit)
    {
        categoryCombo = new Wt::WComboBox(result);
        categoryCombo->addItem("Default");
        categoryCombo->addItem("Extra");
        categoryCombo->setCurrentIndex(0);
        categoryCombo->activated().connect(this, &App::categoryComboChanged);

        messageCombo = new Wt::WComboBox(result);
        messageCombo->addItem("Default 0");
        messageCombo->addItem("Default 1");
        messageCombo->addItem("Default 2");
        messageCombo->setCurrentIndex(0); // Trailer
        messageCombo->activated().connect(this, &App::messageComboChanged);
        isComboBoxInit=true;
    }
    WApplication* app = WApplication::instance();
    std::string categoryNumber = app->internalPathNextPart("/dynamic/");

    if (!categoryNumber.empty())
    {
        if (categoryCombo->currentIndex() != std::stoi(categoryNumber))
        {
            isChanged = true;
            Wt::log("notice") << "(categoryCombo: " << categoryNumber << ")";
            categoryCombo->setCurrentIndex(std::stoi(categoryNumber));
            categoryComboChanged();
        }
        std::string messageNumber = app->internalPathNextPart("/dynamic/" + categoryNumber + "/");
        if (!messageNumber.empty())
        {
            if (messageCombo->currentIndex() != std::stoi(messageNumber))
            {
                isChanged = true;
                Wt::log("notice") << "(messageCombo: " << messageNumber << ")";
                messageCombo->setCurrentIndex(std::stoi(messageNumber));
            }
        }
        isChanged = false;
    }

    if (categoryCombo->currentIndex() == 0)
    {
        switch (messageCombo->currentIndex())
        {
            case 0:
                message_ = "default-0";
                break;
            case 1:
                message_ = "default-1";
                break;
            case 2:
                message_ = "default-2";
                break;
        }
    }
    else if (categoryCombo->currentIndex() == 1)
    {
        switch (messageCombo->currentIndex())
        {
            case 0:
                message_ = "extra-0";
                break;
            case 1:
                message_ = "extra-1";
                break;
            case 2:
                message_ = "extra-2";
                break;
            case 3:
                message_ = "extra-3";
                break;
        }
    }

    new Wt::WText(Wt::WString::tr(message_), result);

    if (bindVideo)
    {
        bindVideo = false;
        // result->bindWidget("contents", contents);
    }
    return result;

}
/* ****************************************************************************
 * categoryComboChanged
 */
void App::categoryComboChanged()
{
    messageCombo->clear();
    messageCombo->setCurrentIndex(0);

    switch (categoryCombo->currentIndex())
    {
        case 0:
            messageCombo->addItem("Default 0");
            messageCombo->addItem("Default 1");
            messageCombo->addItem("Default 2");
            break;
        case 1:
            messageCombo->addItem("Extra 0");
            messageCombo->addItem("Extra 1");
            messageCombo->addItem("Extra 2");
            messageCombo->addItem("Extra 3");
            break;
    }
    if (!isChanged)
    {
        Wt::log("notice") << "(categoryComboChanged: " << std::to_string(categoryCombo->currentIndex()) << ")";
        Wt::WApplication::instance()->setInternalPath("/dynamic/" + std::to_string(categoryCombo->currentIndex()) + "/" + std::to_string(messageCombo->currentIndex()), true);
    }
}
/* ****************************************************************************
 * messageComboChanged
 */
void App::messageComboChanged()
{
    if (!isChanged)
    {
        Wt::log("notice") << "(messageComboChanged: " << std::to_string(messageCombo->currentIndex()) << ")";
        Wt::WApplication::instance()->setInternalPath("/dynamic/" + std::to_string(categoryCombo->currentIndex()) + "/" + std::to_string(messageCombo->currentIndex()), true);
    }
}
/* ****************************************************************************
 * logInternalPath
 */
void App::logInternalPath(const std::string& path)
{
    // simulate an access log for the interal paths
    log("Path Change") << path;

    // As far as I can tell, this would be the same if I did it in combobox change event
    Wt::log("notice") << "(logInternalPath: " << ")";
    WApplication* app = WApplication::instance();
    if (app->internalPathMatches("/dynamic/"))
    {
        std::string categoryNumber = app->internalPathNextPart("/dynamic/");
        if (!categoryNumber.empty())
        {
            std::string messageNumber = app->internalPathNextPart("/dynamic/" + categoryNumber + "/");
            if (!messageNumber.empty())
            {
                Wt::log("notice") << "(logInternalPath: " << categoryNumber + "/" + messageNumber << ")";
                bindVideo = true;
                Dynamically();
            }
        }
    }
}
/* ****************************************************************************
 * setLanguage
 * Currently this is bound to triggered, which fires once for each menu item
 */
void App::handlePopup(int data)
{
    Wt::log("notice") << "(data: " << data << ")";
    if (data == 2) // English
    {
        Wt::log("notice") << "(set language to English: " << ")";
        Wt::WApplication::instance()->setInternalPath("/",  true);
    }
    else if (data == 1) // 中文 (Chinese)
    {
        Wt::log("notice") << "(set language to Chinese: " << ")";
        Wt::WApplication::instance()->setInternalPath("/cn",  true);
    }
    else if (data == 0) // Русский (Russian)
    {
        Wt::log("notice") << "(set language to Russian: " << ")";
        Wt::WApplication::instance()->setInternalPath("/ru",  true);
    }
}
/* ****************************************************************************
 * tr
 */
Wt::WString App::tr(const char *key)
{
    return Wt::WString::tr(key);
}
/* ****************************************************************************
 * create_app
 */
Wt::WApplication* create_app(const Wt::WEnvironment& env)
{
    return new App(env);
}
/* ****************************************************************************
 * main
 */
int main(int argc, char* argv[])
{
    return Wt::WRun(argc, argv, create_app);
}
// --- End of File ------------------------------------------------------------

Attachment: dynamic-menu.xml
Description: XML document

------------------------------------------------------------------------------
Flow-based real-time traffic analytics software. Cisco certified tool.
Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer
Customize your own dashboards, set traffic alerts and generate reports.
Network behavioral analysis & security monitoring. All-in-one tool.
http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to