x::w::main_window
s
own references on their dialogs
x::w::dialog
s can create their own
dialogs, and this applies recursively also.
x::w::dialog
s
own references on their own dialogs, too.
A fundamental concept of the LibCXX Widget Toolkit is that all its objects are reference-counted objects. All references to the object must go out of scope and get destroyed before the underlying objects' destructors get automatically invoked; and all main windows must be destroyed in order for the library to properly clean up and disconnect from the display server.
In main windows, container elements own references to the widgets in the container. This applies to dialogs too. Their parent main window (or their parent dialog) owns a reference on all of its dialogs.
std::unordered_set<std::string> dialogs=main_window->dialogs();
menu.C
gives an example of using dialogs
(), which
returns all identifiers for all dialogs that the
x::w::main_window
(or the
x::w::dialog
) owns.
m->append_items ({ [main_window=x::make_weak_capture(main_window)] (ONLY IN_THREAD, const x::w::list_item_status_info_t &ignore) { main_window.get ([&] (const auto &main_window) { main_window->get_dialog("help_question")->dialog_window->show_all(); }); }, "Question",
menu.C
creates several dialogs, like
“help_question”, for a main window with a menu which
open the various dialogs.
get_dialog
() takes a dialog identifier and
returns the previously-created dialog with this identifier.
The callbacks that get installed for each menu item use it to
locate the appropriate dialog, and make it visible.
The dialog's buttons merely hide their dialog, they don't destroy it,
since their parent main window owns a reference to its dialogs. As
such, when the menu item gets selected again it simply
show_all
()s the same dialog, making it
visible again.
The only way to permanently destroy a dialog is by using
remove_dialog
(); and because the parent
main window owns references on its dialogs, if the main window's last
reference goes out of scope and it gets destroyed (as part of normal
application termination), its dialogs get destroyed too.
This also means that, as shown in the above example, callbacks must capture only weak reference to their parent main window (or parent dialog), because the main window (or the parent dialog) owns (directly or indirectly) references to all elements in the main window (or the dialog), including the menu item with the callback, so the weak capture is required to avoid a circular reference.
auto d=main_window->create_ok_dialog({"example@libcxx.com", true}, "alert", [] (const x::w::factory &f) { f->create_label("Bad input"); }, main_window->destroy_when_closed("example@libcxx.com"));
destroy_when_closed()
returns a closure that's
suitable for an “Ok” or “Cancel” button's
callback (except for create_input_field
()'s
“Ok” callback that takes an additional parameter).
When it gets invoked the specified dialog gets
remove_dialog
(). This example
calls main_window
's
destroy_when_closed
(). The returned closure
invokes main_window
's
remove_dialog
("example@libcxx.com")
(using a weak reference, for the reasons previously stated)
and this
get installed as this new dialog's callback. Thusly, the dialog ends
up removing itself, as a result of “Ok” getting pressed.