Difference between revisions of "Event Driven Programming, Notifications"

From MorphOS Library

(Notifications in MUI: Contents.)
(Notifications in MUI: Contents.)
Line 32: Line 32:
  
 
A notification is triggered when an attribute is set to a specified value. It is often useful to have a notification on '''any''' attribute change. A special value ''MUIV_Notify_EveryTime'' should be used as a triggering value in this case.
 
A notification is triggered when an attribute is set to a specified value. It is often useful to have a notification on '''any''' attribute change. A special value ''MUIV_Notify_EveryTime'' should be used as a triggering value in this case.
 +
 +
The target action of a notification can be any method. There are a few methods designed specifically to be used in notifications:
 +
 +
'''''MUIM_Set()''''' is another method for setting an attribute. It is used, when a notification has to set an attribute on the target object. ''OM_SET()'' is not suitable for using in notifications because it takes a [[Taglists|taglist]] containing attributes to be set. This taglist cannot be built from arguments and must be defined separately. ''MUIM_Set()'' sets a single attribute to a specified value. They are passed to the method directly as two separate arguments. The example below opens a window, when a button is pressed:
 +
 +
DoMethod(button, MUIM_Notify, MUIA_Pressed, FALSE, window, 3, MUIM_Set, MUIA_Window_Open, TRUE);
 +
 +
Those not familiar with MUI may ask why the triggering value is set as ''FALSE''. It is related to the default behaviour of button gadgets. The gadget triggers, when the left mouse button is '''released''', so at the end of a click. The ''MUIA_Pressed'' attribute is set to ''TRUE'' when the mouse button is pushed down, and set to ''FALSE'' when the mouse button is released. Then it is obvious why the notification is set to trigger at ''MUIA_Pressed'' change to ''FALSE''.
 +
 +
'''''MUIM_NoNotifySet()''''' works the same as ''MUIM_Set()'' with one important exception. It does not trigger any notifications set on the target object, on the attribute being changed. It is often used to avoid notification loops, not only in notification, but also standalone in the code.
 +
 +
'''''MUIM_MultiSet()''''' allows for setting the same attribute to the same value for multiple objects. Objects are specified as the method arguments, the last, ending argument should be ''NULL''. When used in notification, it allows for up to 3 objects, due to the limit of total number of action arguments. Here is an example, disabling three buttons after a checkmark is deselected:
 +
 +
DoMethod(checkmark, MUIM_Notify, MUIA_Selected, FALSE, application, 7, MUIM_MultiSet,
 +
  MUIA_Disabled, TRUE, button1, button2, button3, NULL);
 +
 +
What is interesting, the target notification object is completely irrelevant here, it must be a valid object pointer however. The application object is used usually for the purpose, or the notification source object.
 +
 +
'''''MUIM_CallHook()''''' calls an external callback function called a [[hook]]. It is often abused by programmers being reluctant to subclassing standard classes and implementing program functionality as new methods. Calling a method from a notification is usually faster and easier (a hook needs some additional structures to be defined).
 +
 +
'''''MUIM_Application_ReturnID()'''''
  
 
==The Ideal MUI Main Loop==
 
==The Ideal MUI Main Loop==

Revision as of 12:19, 16 November 2010

Grzegorz Kraszewski


Event Driven Programming

The event driven programming is the natural consequence of invention and development of graphical user interfaces. Most of traditional, commandline programs work like a pipe: data are loaded, processed and saved. There is no, or limited user interaction (like adjusting processing parameters, or choosing one of alternative pathes). GUI changes it all. A GUI based program initializes itself, opens a window with some icons and gadgets, then waits for user actions. Fragments of the program are executed in response for user input, after an action is finished, the program backs to waiting. This way the program flow is determined not by the code, but rather by input events sent to the program by user via the operating system. This is the basic paradigm of the event driven programming.


Mzone eventdriven 1.png


Fig. 1. Execution flow of an event driven program.


Notifications in MUI

There are two approaches to input event decoding in an event driven program: centralized and decentralized. The centralized decoding is programmed as a big conditional statement (switch usually, or a long cascade of if-s) inside the main loop of the fig. 1. flowchart. Depending on the decoded event, subroutines performing requested actions are called. The decentralized input event decoding is a more modern idea. In this case, the GUI toolkit receives and handles incoming input events internally and maps them to attribute changes of GUI objects (for example clicking with the mouse on a button, changes its attribute to "pressed"). Then an application programmer can assign actions to attribute changes of choosen objects. This is done by creating notifications on objects.

MUI uses decentralized input event decoding. All input events are mapped to atribute changes of different objects. These are visible GUI gadgets (controls) usually, but some events may be mapped to attributes of a window object, or an application object (the last one has no visible representation). After creating the complete object tree, but before entering the main loop, the program sets up notifications, assigning actions to attribute changes. Notifications can be also created and deleted dynamically at any time.

A notification connects two objects together. The source object is the one, which triggers the action, after one of its attributes changes. The target object is the one, on which the assigned action (method) is performed. The notification is set up by calling MUIM_Notify() method on the source object. Arguments of the method can be divided into the source part and the target part. The general form of MUIM_Notify() call is shown below:

DoMethod(source, MUIM_Notify, attribute, value, target, param_count, action, /* parameters */);

The first four arguments form the source part, the rest is the target part. The complete call can be "translated" to the human language in the following way:


When the source object changes its attribute to the value,
perform action method on the target object with parameters.


There is one argument not explained with the above sentence, param_count namely. This is just the number of parameters following this argument. The minimum number of parameters is 1 (the action method identifier), the maximum one is 7, so the action performed on the target may have no more than 6 parameters.

A notification is triggered when an attribute is set to a specified value. It is often useful to have a notification on any attribute change. A special value MUIV_Notify_EveryTime should be used as a triggering value in this case.

The target action of a notification can be any method. There are a few methods designed specifically to be used in notifications:

MUIM_Set() is another method for setting an attribute. It is used, when a notification has to set an attribute on the target object. OM_SET() is not suitable for using in notifications because it takes a taglist containing attributes to be set. This taglist cannot be built from arguments and must be defined separately. MUIM_Set() sets a single attribute to a specified value. They are passed to the method directly as two separate arguments. The example below opens a window, when a button is pressed:

DoMethod(button, MUIM_Notify, MUIA_Pressed, FALSE, window, 3, MUIM_Set, MUIA_Window_Open, TRUE);

Those not familiar with MUI may ask why the triggering value is set as FALSE. It is related to the default behaviour of button gadgets. The gadget triggers, when the left mouse button is released, so at the end of a click. The MUIA_Pressed attribute is set to TRUE when the mouse button is pushed down, and set to FALSE when the mouse button is released. Then it is obvious why the notification is set to trigger at MUIA_Pressed change to FALSE.

MUIM_NoNotifySet() works the same as MUIM_Set() with one important exception. It does not trigger any notifications set on the target object, on the attribute being changed. It is often used to avoid notification loops, not only in notification, but also standalone in the code.

MUIM_MultiSet() allows for setting the same attribute to the same value for multiple objects. Objects are specified as the method arguments, the last, ending argument should be NULL. When used in notification, it allows for up to 3 objects, due to the limit of total number of action arguments. Here is an example, disabling three buttons after a checkmark is deselected:

DoMethod(checkmark, MUIM_Notify, MUIA_Selected, FALSE, application, 7, MUIM_MultiSet,
 MUIA_Disabled, TRUE, button1, button2, button3, NULL);

What is interesting, the target notification object is completely irrelevant here, it must be a valid object pointer however. The application object is used usually for the purpose, or the notification source object.

MUIM_CallHook() calls an external callback function called a hook. It is often abused by programmers being reluctant to subclassing standard classes and implementing program functionality as new methods. Calling a method from a notification is usually faster and easier (a hook needs some additional structures to be defined).

MUIM_Application_ReturnID()

The Ideal MUI Main Loop