Difference between revisions of "Locating Objects in the Object Tree"

From MorphOS Library

m (copy and paste bug fix)
m
Line 1: Line 1:
 
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:
 
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:
* 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 number of global variables reaches 50, 100 or more.  
+
* 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 ''Application'' one). A good idea, but a bit tedious to implement. Object's instance data area does not exist until the object is fully created 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.
+
* 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 fully created 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 ''MUIA_UserData'' attribute and ''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.
+
* 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.
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 ''MUIM_FindUData()'' method on a direct or indirect parent object, for example on the master ''Application'' one.
+
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.
  
 
  #define OBJ_SOME_BUTTON 36
 
  #define OBJ_SOME_BUTTON 36
Line 17: Line 17:
 
  some_button = (Object*)DoMethod(App, MUIM_FindUData, OBJ_SOME_BUTTON);
 
  some_button = (Object*)DoMethod(App, MUIM_FindUData, OBJ_SOME_BUTTON);
  
This operation is so common, that it is usually encapsulated in a macro:
+
This operation is so common that it is usually encapsulated in a macro:
  
 
  #define findobj(id, parent) (Object*)DoMethod(parent, MUIM_FindUData, id)
 
  #define findobj(id, parent) (Object*)DoMethod(parent, MUIM_FindUData, id)
Line 23: Line 23:
 
  some_button = findobj(OBJ_SOME_BUTTON, App);
 
  some_button = findobj(OBJ_SOME_BUTTON, App);
  
The macro may be of course used directly in other functions, like in this example changing the button label:
+
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");
 
  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.
 
Note that the ''findobj()'' macro is not defined in the system MUI headers, so it should be defined in the application code.

Revision as of 08:53, 7 January 2011

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:

  • 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 fully created 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.

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.

#define OBJ_SOME_BUTTON 36

/* Somewhere in the initial tags for the button */
MUIA_UserData, OBJ_SOME_BUTTON,
/* ... */

/* Let's get the pointer to the button now */

Object *some_button;

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.