A popup menu is a menu presented in a popup window. The menu implements a typical context menu, with support for submenu's.

WPopupMenu is not to be confused with WMenu which implements an always-visible navigation menu for a web application.

When initially created, the menu is invisible, until popup() or exec() is called. Then, the menu will remain visible until an item is selected, or the user cancels the menu (by pressing the Escape key or clicking elsewhere).

The implementation assumes availability of JavaScript to position the menu at the current mouse position and provide feed-back of the currently selected item.

WPopupMenu is similar in use to WDialog. So there are two ways of using the menu. The simplest way is to use one of the exec() methods, apply a reentrant event loop and wait until the user selected an item or cancelled the popup menu (by pressing Escape or clicking elsewhere).

Preferably, use one of the popup() methods to show the menu and listen to the aboutToHide signal where you read the result() (the last triggered menu item). If you listen to the aboutToHide signal of a parent popup it will also be triggered by its child popups.

You have several options to react to the selection of an item:

  • You can use the WMenuItem itself to identify the action, perhaps by specialization or by simply by binding custom data using WMenuItem::setData().
  • You can use a lambda function to connect to each of the listeners. In C++, you can use boost::bind() to bind parameters that identify the selected item.
  • You can bind a separate method to each item's WMenuItem::triggered signal.

Example
source
#include <Wt/WBreak.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WMenuItem.h>
#include <Wt/WMessageBox.h>
#include <Wt/WPopupMenu.h>
#include <Wt/WPushButton.h>
#include <Wt/WText.h>

using namespace Wt;

auto container = std::make_unique<Wt::WContainerWidget>();

auto popupPtr = std::make_unique<Wt::WPopupMenu>();
auto popup = popupPtr.get();

auto statusPtr = std::make_unique<Wt::WText>();
auto status = statusPtr.get();
status->setMargin(10, Wt::Side::Left | Wt::Side::Right);

auto outPtr = std::make_unique<Wt::WText>();
auto out = outPtr.get();

// Create some menu items for the popup menu
popup->addItem("Connect")->triggered().connect([=] {
    out->setText("<p>Connecting...</p>");
});

popup->addItem("Disconnect")->triggered().connect([=] {
    out->setText("<p>You are disconnected now.</p>");
});

popup->addSeparator();

popup->addItem("icons/house.png", "I'm home")->triggered().connect([=] {
    out->setText("");
});

Wt::WMenuItem *item = popup->addItem("Don't disturb");
item->setCheckable(true);

item->triggered().connect([=] {
    out->setText(Wt::WString("<p>{1} item is {2}.</p>")
                 .arg(item->text())
                 .arg(item->isChecked() ? "checked" : "unchecked"));
});

popup->addSeparator();

// Create a submenu for the popup menu.
auto subMenuPtr = std::make_unique<Wt::WPopupMenu>();
auto subMenu = subMenuPtr.get();

subMenu->addItem("Contents")->triggered().connect([=] {
    out->setText("<p>This could be a link to /contents.html.</p>");
});

subMenu->addItem("Index")->triggered().connect([=] {
    out->setText("<p>This could be a link to /index.html.</p>");
});

subMenu->addSeparator();
subMenu->addItem("About")->triggered().connect([=] {
    auto messageBox = subMenu->addChild(
            std::make_unique<Wt::WMessageBox>
            ("About", "<p>This is a program to make connections.</p>",
             Wt::Icon::Information,
             Wt::StandardButton::Ok));
    messageBox->show();
    messageBox->buttonClicked().connect([=] {
      subMenu->removeChild(messageBox);
    });
});

// Assign the submenu to the parent popup menu.
popup->addMenu("Help", std::move(subMenuPtr));

Wt::WPushButton *button = container->addNew<Wt::WPushButton>();
button->setMenu(std::move(popupPtr));

// React to an item selection
popup->itemSelected().connect([=] (Wt::WMenuItem *selectedItem) {
    status->setText
        (Wt::WString("Selected menu item: {1}.")
         .arg(selectedItem->text()));
});

container->addWidget(std::move(statusPtr));
container->addWidget(std::move(outPtr));

Top