Locating Objects in the Object Tree
After the complete object tree is created, there is no direct access to any object except the main Application object. A way to access other objects is needed. There are a few ways to do this:
The last approach works as follows: every object to be searched has the MUIA_UserData attribute set to some predefined unique value. Then at any time the object may be found by this value using the MUIM_FindUData() method on a direct or indirect parent object, for example on the master Application object.
- Storing pointers to objects in global variables. This is the simplest way and may work well in simple projects. The disadvantage is it breaks object oriented design principles (like data encapsulation) and creates a mess when the number of global variables reaches 50, 100 or more.
- Store pointers in fields of some subclass instance data (for example the Application instance). A good idea, but a bit tedious to implement. An object's instance data area does not exist until the object is created (to be precise – until rootclass constructor is executed) and the Application object is created as the last one. Then pointers to subobjects have to be stored in some temporary variables. This technique also requires that a parent object of the cached one is an instance of a custom (subclassed) class and the parent creates its subobjects inside the constructor, which is not always true.
- Use the MUIA_UserData attribute and the MUIM_FindUData() method to find objects dynamically. This is the best solution when objects are accessed rarely (for example once, just to set notifications). For frequently accessed objects (let's say several times a second) it may be combined with caching objects' pointers in an instance data of some subclassed object.
#define OBJ_SOME_BUTTON 36
/* Somewhere in the initial tags for the button */
/* ... */
/* Let's get the pointer to the button now */
some_button = (Object*)DoMethod(App, MUIM_FindUData, OBJ_SOME_BUTTON);
This operation is so common that it is usually encapsulated in a macro:
#define findobj(id, parent) (Object*)DoMethod(parent, MUIM_FindUData, id)
some_button = findobj(OBJ_SOME_BUTTON, App);
The macro may of course be used directly in other functions, like in this example changing the button label:
set(findobj(OBJ_SOME_BUTTON, App), MUIA_Text_Contents, "Press Me");
Note that the findobj() macro is not defined in the system MUI headers, so it should be defined in the application code.