In trivial event functions you might only want to access the object that the event is associated with, for instance you might want to use a button's onClick event to change the button text. In this case the object is immediately available as the first argument to the event function. But, more often, you will wand to find some other object in the form or report. There are a number of ways of doing this.
The first is the getNamedCtrl method which has been show above. This method is applied to an object and is given a string argument which is the path to some other object. So, for instance, if you have a two buttons A and B which are located in the same block or container, and you want to change the text of B from A's onClick event, the code would be like:
def eventFunc (button) : button.getNamedCtrl("../B").setText("A was clicked!") |
The .. part of the path takes you to the parent of the button (the block or container), then the object named B (the other button) is located. This is just like a path name in the Unix file system (or windows but with forward rather than backward slash). The slashes split the path up into the object name at each step. There are are few special cases. getRoot() means the topmost object, while getBlock() means the enclosing block (so, a field named address in the enclosing block would have the path getBlock()/address). Note that there must not be any spaces in getBlock()! If the path starts with a leading slash, then it starts at the root (so /people/person is the same as getRoot()/person).
See the section Finding Objects in the Editor for information on how to make finding paths easy.
getNamedCtrl() is particularly useful if you want to build the path at run time. For instance, suppose that you have a button P whose onClick event function should disable buttons Q, R, S and T. In this case you could write:
def eventFunc (button) : for name in [ 'P', 'Q', 'R', 'S' ] : button.getNamedCtrl("../" + name).setEnabled (0) |
The next method (which appeared with Rekall 2.4.0) uses a notation is more concise, though a tad less flexible. The example above which sets the text of another button becomes as shown below:
def eventFunc (button) : button.__parent__.B.setText("A was clicked!") |
The __parent__ is equivalent to the .. using getNamedCtrl() and moves to the parent object. Then, since B is not the name of any method, Rekall looks to see if the object has a child object named B. Similarly to the path components above, you can use __root__ to get the top-level form or report object, and __block__ to get the enclosing block. While we are here, this can be written more concisely still as:
def eventFunc (button) : button.__parent__.B.text = "A was clicked!" |
Here, text is a property of a button that can be set or read. This is described below.
Using paths means that (unless you have two objects with the same name in the same block or container) you can find your way from one object to another. However, if you move objects around in a form, you might need to adjust the paths. This can be annoying (especially as you don't find your mistakes until the appropriate script runs, so if its obsure and is used infrequently, you might not find it for some time), so from Rekall 2.4.3 the following extension is available. The root object (ie., the toplevel form or report object) has a property __objects__ from which all objects in the document can be accessed in one step. So, if clicking button btnDisable should disable a button named btnSaveRecord then the onClick event function for the former can be:
def eventFunc (button) : button.__root__.__objects__.btnSaveRecord.setEnabled (0) |
This works wherever btnSaveRecord is in the form. You can move btnSaveRecord around and it will still work! The only proviso is that there must only be one such named button; if you have two or more with that name then there is no guarantee which you get. Also, objects which are inside linked components (see the section on components) are not included. Finally, you can shorten this as below; within an event function (or slot, see later) the symbol root will always refer to the form or report root. Note that this does not work in separate script modules (for those into python root is an entry in the local dictionary for the event function).
def eventFunc (button) : root.__objects__.btnSaveRecord.setEnabled (0) |