Chapter 5

The Messaging System


5.1 Message handlers and argument list

The message passing mechanism is the primary means by which viola objects communicate with each other. In conjunction with messaging, scripting give objects a way to decide what to do with the messages they receive. When a user does something with the mouse and keyboard, event messages may be generated and passed to the relevent objects. Those objects can, as dictated by their scripts, perform some function, and/or delegate tasks by passing out more messages to other objects.

This is what actually happens in message passing. The basic idea is to designate an object, load values into an "argument" list, and give the 'flow' control to the object, execute the object's script so the object can examine the content of the argument list, and do its thing.

For example, the following statement sends a "render" message to an object called "hello".

send("hello", "render");

The meaning of the message strings is largely a matter of convention -- objects agreeing on some protocol. So, aside from the ten or so hard coded message (see chapter 5.3 for listing), all other mesasge strings are just aritrary strings which cooperating objects have agreement upon.

Like, the message word "show" is just a convention recognized by the "res.dialog" object. Likewise, "callback_exit" and "callback_nevermind", is some almost arbitrary string that object "hello" tells obj "res.dialog" to send back, depending on whether the user clicks on "Yes" or "No" button on the dialog box.

Note that the following two object calling syntaxes are equivalent, but the first form is prefered (easier to distinquish an object reference from method reference):

send(objectName, messages)

objectName(messages)

Intercepting a Message

For example, the following field draws an X whose endpoints extend to the four corners of the button:

\class {field} \script { if (arg[0] == "render") { w = get("width"); h = get("height"); drawLine(0, 0, w, h); drawLine(0, h, w, 0); } usual(); }

The object is of the "field" class, which is a very basic class of objects that is not much more than an object with a window. The script makes it draw an X when the objects is told to "render" itself.

The field class does not draw anything in its window, unlike say, a text button, that draws a border. To draw our X after the usual rendering method of the object, we can write the script in the following way to achieve that effect. The idea is to execute the usual() method first, then do our special drawings, then exit the script. Without the explicit return statement, the control would flow into usual() again which is redundant and could possibly undo our drawings (usual() might clear the window before its own drawings).

\class {txtButton} \script { if (arg[0] == "render") { usual(); w = get("width"); h = get("height"); drawLine(0, 0, w, h); drawLine(0, h, w, 0); return; } usual(); }

The way to pass message to an object is by passing them in the "arg" list variable. The list is constructed by object calling. The list indexing is consecutive and starts with 0. First argument is arg[0], second argument is arg[1], and so on. Like any list, the argument count can be had by evaluating arg[].

example object:

\class {generic} \name {sum} \script { if (arg[0] == "do") { for (total = 0, i = 1; i < arg[]; total += arg[i]); return total; } usual(); /* do the usual things */ }

to call it:

print(sum("do", 1900, 90, 2));

Output:

1992

To send a message recursively to a list of objects, use methods like objectListSend() or deepObjectListSend().

5.2 Delaying messages

It's some times useful to procrastinate the arrival of a message, or to make a "procedure call" after T time. To do this, use the after() method.

For example, the object calling this statement will receive a "buttonPress" message in 1000 miliseconds.

after(1000, self(), "buttonPress");

Here's an application that continuously updates its display of date and time. The trick here is to just keep sending self a message after 1000 miniseconds.

\class {txtDisp} \name {date} \script { switch (arg[0]) { case "tick": set("content", date()); after(1000, self(), "tick")); return; break; case "init": usual(); after(1, self(), "tick")); return; break; } usual(); } \width {300} \height {20} \

[XXX info on how to postpone doing work after receiving a message. How to call back to one self, and why that's useful sometimes.]

5.3 Source of messages

Discuss the events and processes that can generates messages. Trace the paths that a message might travel, and how it can be handled by scripts. Mention about messages that can be triggered by IPC events.

Many messages are direct consequences of the windowing system. For example, when an object's window is exposed, the object receives a "render" message. The idea, of course, if to notify the object that it ought to render itself. Unless the object has customized message handler for the message "render" that does customized rendering, the control will eventually fall to the default scripts which does the expected thing -- drawn to look like buttons with text label.

List of messages which are hard-coded and conventional.

By Viola (and operating system):

arg[0] arg[1]..arg[n] See also ----------------- --------------------- -------------------- "keyPress" key() "keyRelease" "buttonPress" mouseButton() "buttonRelease" "enter" "leave" "input" input(), socket/tty classes "config" x, y, width, height "expose" "init"
Message (arg[0])arg[1]..arg[n]
"keyPress"
"keyRelease"
"buttonPress"
"buttonRelease"
"enter"
"leave"
"input"
"config" x, y, width, height
"expose"
"init"

GOTO Preface, Previous Chapter (4), Next Chapter (6)