On Dienstag, Mär 18, 2003, at 12:33 Europe/Vienna, Daan Leijen wrote:
Hi all,
2) For every callback, there should be a register function.
The register function should return an IO action that can be used to
unregister the callback.
I disagree with this design. It is very awkward to install callbacks
this way as we
have to maintain the "unregister" function. We can no longer use
"nice" syntax like:
button [on click := messageBox "hi there"]
Yes, that looks nicer, but it now we can have only one callback for one
event; I believe the people who first brought this design up (I was
only copying what I had read on this list) were thinking of allowing
multiple callbacks to be installed for a single event, as can be done
using GTK's signal/slot mechanism.
So what about...
2) Installing Callbacks
2a)
For every callback, there should be a register function.
The register function should return an IO action that can be
used to unregister the callback.
There can be multiple callbacks for one event.
2b)
Callbacks are set using a general attribute get/set mechanism
that we will probably design soon.
There can be only one callback for one event.
Please note that it is very easy to emulate one option using the other,
so the features of the backend libraries are probably not an issue here.
2a can, of course, be useful in many situations. I'm not sure if I want
the nice syntax or the nice functionality, so I withdraw my vote on 2)
and abstain for now. Everyone please keep discussing :-)
I'd like to provide an example of where I'd prefer to have 2a:
Suppose we have a document window. In order to support a "Save
Changes?" dialog, I'd perhaps add a callback for the "window about to
close" event. No problems here.
Suppose that we also have a utility window that shows information about
some item in the document. When the document window closes, the utility
window closes, too (we'd like to have a second "close" callback on the
document window), but the utility window can also be closed by the user
before the document closes (we'd like to uninstall our "close" callback
in that case).
In most other situations, I would probably prefer the single-callback
approach because of the opportunities for nicer syntax.
This mechanism is enough to build a nice framework around. For
example, you
could add a callback to the existing ones.
buttonAddOnClick io button
= do prev <-buttonGetOnClick button
buttonSetOnClick (do{ io; prev }) button
Which is fine as long as you don't want to uninstall a callback. And we
might want to use a threadsafe buttonModifyOnClick :: Button -> (IO ()
-> IO ()) -> IO () instead.
The only think lacking is indeed the "unregister" call but I think it
is a highly
unusual thing to deinstall a callback without replacement on an
existing widget.
Normally, the callbacks are deinstalled when the widget dies.
But for completeness, we might want to have:
buttonIgnoreOnClick :: Button -> IO ()
Definitely. For button clicks, it is a non-issue, but some X folk have
said that mouse moved events are really bad for remote connections, and
I wouldn't bet it's so unusual to track mouse movements only for a
short period of time and then uninstall the callback.
Cheers,
Wolfgang
|