Gnocl Cookbook‎ > ‎

Redirecting event data to one of a number of choices

A simple approach to managing a large number of interactive menu choice.

Tcl is really good at making the difficult easy. Imagine a paint program with a range of tools, the action of which will differ yet they will all act to change a single buffer. What then, is the simplest way of for the application to decide how to pass  information about user interaction over to the appropriate functionality. I remember seeing, many years ago, the source code for the AT&T Tips paint software (running on now ancient Targa and Vista display buffers). Here the operator would make a choice, a global variable was set and the input data passed on after entering a cascade of switch/case operations. Would it not be simpler to have a unified series of arguments passed to a handling function the pointer to which is set rather than a variable?  This is how Gtk handles event programming and we can use a similar principle in our Gnocl scripts.

Consider the following code segment to make a typical paint toolbar:

# create tools
set tools [gnocl::box]
foreach i {clear pencil eraser picker fill undo redo copy paste} {
    catch { $tools add [gnocl::button \
                -tooltip $i \
                -name $i \
                -icon "%/./icons/$i.png" \
                -relief none \
                -onClicked { set handler(active) [%w cget -name] }]

All looks pretty straight forward, but further examination of the -onClicked command shows that the global variable handler(active) has been set to the name of of this widget.  This, of course assumes that a following procedure exists. The following example is for a simple pixel drawing pencil.

proc pencil {w x y b m} { ....... }


w    -the widget-id of the calling widget
x    -the cursor x coordinate
y    -the curose y coordinate
   -the button event
m    -the state of the keyboard modifiers

Now, whenever user interaction occurs in the image  drawing/edit areas, all event information can be passed directly as the following snippet shows. All that has happened is that the name the handler script has changed -simple!

set img1 [gnocl::image -image "%?$pb1"]
set ebox1 [gnocl::eventBox \
    -child $img1 \
    -onMotion {  $handler(active) %w %x %y %b %m  }]

Here a gnocl::image, which has no inherent signal mask is contained in a gnocl::eventBox.  Whenever a motion event occurs, the interpreter will involk the preselected handling function.

The basic notion then is quite simple and potentially saves a whole pile checking issues. There's only one issue though. The -name option used by Glade produced UIs, so care must be taken to ensure consistency between proc and widget naming during the layout process.