[GUI] GUIs and events/callbacks.

George Russell ger@tzi.de
Thu, 06 Mar 2003 19:13:08 +0100


I think I've pointed out that the main difference between GIO and HTk
is that HTk uses composable events, while GIO, like most other Haskell
GUI's (including GTk+hs) use callbacks.

Now of course I'm biased, and I prefer events to callbacks, but I
appreciate the arguments that have been made that including composable
events in a GUI would simply involve adding too much heavy machinery
which doesn't have anything to do with graphics.

But I think I have a solution to this, which I would like to propose.
This is that a GUI standard specify events, but *doesn't* specify that
they be composable.  Then they would be trivial to implement, and still
(in my opinion) be better than callbacks.  Also systems like HTk could
of course add an extra module which did provide the composition
operators.

So, in detail, the GUI standard should have a new type

    Event a

which means "Event carrying a value a".

To generate for example something like a button click event we could
have a function

    clicked :: Clickable widget => widget -> IO (Event ())

Thus, after this function is called, the returned "event" would
happen each time the user clicks the button.

A mouse click event might, for example, have type (Event (Int,Int))
giving the co-ordinates of the mouse pointer at the time of the click.

To "listen" for events, two functions would be provided:

    sync :: Event a -> IO a

which blocks until the event happens (or returns immediately if a
queued occurence of this event has already happened), and

    setCallBack :: Event a -> (a -> IO ()) -> IO ()

which added an action to be performed each time the event happens.

There are questions to be asked about what happens when you have
multiple consumers of the same event.  I think it should be guaranteed
that when an event happens, only one consumer gets to hear about it,
but which does not perhaps need to be specified.  (I don't think this
is very likely anyway.)

Summary
-------

Advantages over Composable Events.
    easier to implement.

Advantages over callbacks:
    can easily be extended to composable events
    the "sync" operator is more powerful than callbacks (without being
    particularly hard to implement).  For example, I think all or at
    least most of the call-back-based solutions to the
    "simple GUI Example" at John Meacham's page

http://repetae.net/john/computer/haskell/gui/

    contain the following bug: if the user clicks
    twice very rapidly on the button, the second click will be ignored.
    In general the click-handling routines can run concurrently,
    perhaps modifying common shared data, and leading to all sorts of
    trouble, unless the user uses locks.  It seems clear that what
    is wanted here is sync, not callbacks.