Attaching application data to widgets

All widgets, including the main application window, have an opaque appdata member that LibCXX Widget Toolkit does not use itself. appdata is an opaque x::ptr<x::obj> object, a reference-counted object. See LibCXX's documentation for more information.

appdata provides convenient means for an application to attach its own data to a widget, by deriving from x::obj, and saving a x::ref to it in appdata.

With application windows having complicated layouts, and a large number of widgets, it's more convenient to stash away a direct reference to a particular widget, rather than having to drill down and find it, each time. As explained in the section called “Containers own references to the widgets in the container”, LibCXX Widget Toolkit's containers own references to their elements, and in order for application windows and their elements to be properly destroyed and terminated the application must release its own references to them. With LibCXX Widget Toolkit built on top of LibCXX's reference-counted object framework, a lingering reference from an application to some widget will prevent proper destruction of widgets.

The appdata provides one convenient way to compile a list of all widgets in one place, safely:

The earlier example in this chapter gives an example of this approach. inputfieldsandbuttons.C creates a window containing, amongst other things, two x::w::input_field. Besides being placed into the window, they're also placed into an object that's attached to the main window's appdata. When the window gets closed the application retrieves the main window's appdata, retrieves the two input fields, and prints their contents.

#include <xrefptr_traits.H>
#include "inputfields.inc.H"

class appdataObj : virtual public x::obj, public inputfields {
public:

	using inputfields::inputfields;
};

typedef x::ref<appdataObj> appdata_t;

The sample program uses some supporting framework from the LibCXX base classes and templates library. The Makefile in the examples directory runs a stylesheet to process inputfields.xml, a simplistic list of fields and their types. This generates a header file that declares two classes. The first one has a list of x::ptrs for all fields. The declared x::ptrs are convenient to have when creating them, piecemeal.

The second class is inputfields, with the final collection of the listed fields, as their natural x::refs. This is multiply-inherited with x::obj to produce a reference-counted object, an appdata_t. This gets create()d and attached as the x::w::main_window's appdata.

Before exiting, the sample program retrieves the main window's appdata, and shows the contents of the input fields.

Every widget has an available appdata. The application can use this to attach an object to any widget; but it is important to understand that the widget owns a reference to its appdata so this object should not have its own reference to the widget or to any of its parent container elements (see the section called “Containers own references to the widgets in the container” for more information). Otherwise this creates a problematic circular reference. With some care, it's possible to use weak pointers, though.

See Chapter 18, The book layout manager for another example of using appdata. See the section called “Using singleton objects” for a different approach to conveniently compiling a collection of all objects in a manner that's compatible with LibCXX Widget Toolkit's rules for reference-counted objects.