Index
Setting up a context popup menu is a two step process:
Use create_popup_menu
() to create the
contents of the popup menu.
Use install_contextpopup_callback
() to
install a callback that gets executed in response to the
right pointer button click.
The executed callback has no obligation to do anything in particular,
such as displaying a popup menu. All that happens
is that it gets executed by the pointer's right button getting clicked
with the pointer position on top of the widget.
popupmenu1.C
demonstrates the expected behavior: the callback
simply show
()s the context popup menu.
/* ** Copyright 2018-2021 Double Precision, Inc. ** See COPYING for distribution information. */ #include "config.h" #include "close_flag.H" #include <x/exception.H> #include <x/destroy_callback.H> #include <x/appid.H> #include <x/w/main_window.H> #include <x/w/gridlayoutmanager.H> #include <x/w/gridfactory.H> #include <x/w/label.H> #include <x/w/text_param_literals.H> #include <x/w/font_literals.H> #include <x/w/container.H> #include <x/w/listlayoutmanager.H> #include <string> #include <iostream> std::string x::appid() noexcept { return "popupmenu1.examples.w.libcxx.com"; } // This is the creator lambda, that gets passed to create_mainwindow() below, // factored out for readability. void create_mainwindow(const x::w::main_window &main_window) { auto layout=main_window->gridlayout(); x::w::gridfactory factory=layout->append_row(); // Besides the right alignment, set the vertical alignment of the // label to middle, it looks better. auto label=factory->padding(3).create_label({ "liberation sans; point_size=20"_font, "Right click on me, please" }); // Create a popup menu. The menu items get created just like they // get created for an ordinary menu, using the list layout manager. x::w::container popup_menu1=label->create_popup_menu ([] (const x::w::listlayoutmanager &lm) { lm->append_items({ [](ONLY IN_THREAD, const auto &info) { std::cout << "New" << std::endl; }, "New", [](ONLY IN_THREAD, const auto &info) { std::cout << "Open" << std::endl; }, "Open", [](ONLY IN_THREAD, const auto &info) { std::cout << "Close" << std::endl; }, "Close", }); }); // Install a callback for the context popup action, right button // click. The callback captures the menu popup, by reference, and // show()s it. label->install_contextpopup_callback ([popup_menu1] (ONLY IN_THREAD, const x::w::element &my_element, const x::w::callback_trigger_t &trigger, const x::w::busy &mcguffin) { popup_menu1->show(); }); } void popupmenu1() { x::destroy_callback::base::guard guard; auto close_flag=close_flag_ref::create(); auto main_window=x::w::main_window::create ([&] (const auto &main_window) { create_mainwindow(main_window); }); main_window->on_disconnect([] { _exit(1); }); guard(main_window->connection_mcguffin()); main_window->set_window_title("Click the label for a popup"); main_window->on_delete ([close_flag] (ONLY IN_THREAD, const x::w::busy &ignore) { close_flag->close(); }); main_window->show_all(); close_flag->wait(); } int main(int argc, char **argv) { try { popupmenu1(); } catch (const x::exception &e) { e->caught(); exit(1); } return 0; }
The context popup menu does not own a reference on its widget, and the widget does not own a reference on its context popup menu, but all other rules for captured references apply. The callback's first parameter is a reference to its widget, and this is done in a manner that does not violate the rules. Context popup callbacks often need to use their widgets, and this avoids the chore of weakly-capturing their widgets, and recovering the strong reference in the callback.
In this example, the context popup gets captured by value, by
the installed callback. The installed callback exists as long as the
context popup remains installed: as long as its widget exists,
or until a replacement context popup callback gets installed (only
one context popup callback exists for each widget),
or until remove_contextpopup_callback
()
explicitly removes it.
create_popup_menu
()'s parameter is a
creator lambda whose job is to create the contents of the popup menu.
The menu gets created the same way as normal
application menus. The lambda receives the list layout
manager as its parameter, and proceeds to create the menu items.
create_popup_menu
() returns an opaque
container that represents the popup menu.
show
() it makes it appear next to the current
pointer location.
It is possible to modify the contents of the context popup menu,
using get_layoutmanager
() to obtain its
list layout manager, and using the list layout manager's methods.
However, since a context popup menu's creation is not dependent on
the context popup callback, it is possible to simply create a
new context popup menu, on demand.
Prev | Up | Next |
Using the mouse pointer or the keyboard with menus | Table Of Contents | Creating new context popup menus on demand |