Loading...
 

Messages

Events/Messages

Events are an essential construct for process control within the ClassiX architecture. They serve

  • the communication between the environment (interface, WebService, TAPI, ...) and ClassiX
  • as interface between ClassiX modules
  • as communication channel between the ClassiX model classes and InstantView (e.g. for formula evaluation)
  • as an abstraction mechanism for the developer
  • as interface for third-party applications (e.g. CORBA)

User-defined messages and predefined system events

On the one hand, there are so-called system events, which are already known to the system. These are used to inform about predefined events (e.g. button was pressed: Message SELECT is triggered).

On the other hand, the InstantView developer can declare own events with the InstantView-Statement Message.

Apart from the fact that system events no longer need to be declared and are sent by the system on specific events, there is no difference between custom events and system events: both are received and can be sent in the same way. Therefore, there is often no clear distinction between them.

Receiving an event

An event can be handled in InstantView code either at the level of a module or at the level of a window (or widget). This allows the context of an event to be defined: A handling of the SELECT event in a button is executed exactly when this one button is clicked.

209330 If the ClassiX system does not find the event to be triggered in a widget, the parent widgets are searched for this event and the event is triggered at this widget if necessary. This way it is e.g. possible to intercept an event like the F2 key for all widgets within a group.

Excluded from this are the events CURRENT, NON_CURRENT and INITIALIZE

Motivation: These events are sent specifically to individual widgets.
Example: If the focus changes from Debit to Credit in the following example, Debit receives a NON_CURRENT and Credit a CURRENT. The enclosing group AccountingGrp remains active throughout. A NON_CURRENT in the group may therefore only be triggered when none of the widgets in the group is active. If F2 was pressed in Debit, F2 was pressed implicitly in the group. To intercept this in the group is therefore useful and one does not lose any specificity.

Group(AccountingGrp, 0, 0, 340, 102) [ F2: ClearWindow ] { Numeric(Debit, 7, 14, 208) Numeric(Credit, 224, 14, 50) }

For events sent by the machine, the context under which the subsequent InstantView code runs is also set according to the "recipient" (i.e., window, widget, or module). This context makes it possible to omit parameters for certain commands (e.g. the window name for the FillWindow command).

Sending messages

Apart from providers, messages are the only means by which programme code can be activated from one module A in another module B(encapsulation in the sense of object orientation).

A message is sent to other Window objects and modules using SendMsg, PostMsg, SendMsg(..., SUPER) or SendMsg(..., DIRECT), and this triggers execution of the statements associated with the message.

Sequence rules

If a message has been sent via SendMsg, the following rules about the order of recipients apply:

  • If several modules receive the same message, the order (between the modules) is random.
  • Modules come before window objects: If a module and window objects of this module react to the same message, the command sequence is always executed first for the module.
  • For Window objects on the same level (the parent-child hierarchy) the order is random.
  • It is guaranteed that a superordinate Window object always receives a message earlier than the subordinate Window objects.

Registering messages

So from InstantView, both types of events can be received and sent in the same way. The ClassiX system itself initially only sends predefined system events.

In some cases it is useful for the code organisation to register any events explicitly on the system. For this purpose, the system is informed of these events via certain methods, which are then called in the corresponding case. For example SystemObject::RegisterAttentionNotification, where the event is triggered when an attention notification is to be opened.

Web service messages

Web service messages are an exception to this division. These are user-defined messages, i.e. they must be declared, but are called up by the system using a naming convention when an end point is called up on the Web. For example, a GET request to the address /fetch_data results in the message FETCH_DATA_GET being executed.

See CX_WEB_SERVICE_MANAGER.

Security

For security purposes, messages can be prevented using a CX_MESSAGE_SECURITY object. See the security concept of ClassiX.

Example

In the following we will take a closer look at the process of sending a message X.
The window in module A is already open; we can press the "push me" button.

First a definition: the current module. The InstantView® interpreter's run-time system considers exactly one of the modules as the current module - it is always the module whose program code is currently being executed.

Pressing the button makes module A the current module. If another module was previously current, CURRENT is triggered for module A; i.e. the instruction sequence Current_at_A is executed before the SendMsg(X) instruction associated with the button is executed.
If A was already the current module, only SendMsg(X) is executed.

 msgdocA.bmp (1430430 bytes)

The receiver module is only referred to by an external instruction, i.e. it is - when we press the button for the first time - not yet loaded.
The external instruction in the source code already corresponds to an internal representation of a module B - a reduced variant that can only receive message X, in order to then load the "correct" module B as a reaction.
Before message X enables loading, module A loses its status as the current module and the instructions NonCurrent_at_A are executed. Then the source code from the file B.MOD is loaded (with tests to make sure that B.MOD also contains module B). If File B.MOD contained the source code of other modules, these would now also be loaded.
Now message X can be received from the "real" module B.

 MsgDocB.bmp (1395054 Byte)

Receiving a message means nothing else than executing all instructions bound to the message - and for this purpose module B must first become the current module. Therefore CURRENT is triggered first (Current_at_B is called). Because this is the first call for module B, INITIALIZE is then triggered - i.e. DoSomeInitializationStuff is executed. Afterwards it is finally Receive_X_at_B's turn - the actual destination of message X.
Receive_X_at_w1 is not executed - a window object can only receive a message if the window is open.

If we press the button for the second time, module B is not loaded and INITIALIZE is not triggered.
In addition, assuming that someone (e.g. with SendMsg(Y)) has opened the window in module B, SendMsg(X) now runs as follows:

 MsgDocC.bmp (1400310 Byte)

Number 1 is missing in the figure, because NON_CURRENT is triggered first in module A.