[GUI] Another RFC on setting and getting.

Glynn Clements glynn.clements@virgin.net
Sat, 5 Apr 2003 06:55:28 +0100


Axel Simon wrote:

> - Callbacks get separate functions which called on<WidgetName><ActionName>

Just on<ActionName> would be better. The "activate" callback is the
same callback whether it's a push-button, toggle-button, etc.

> I would like propose the following basic setup, together with the 
> questions how read only attribute can fit in. Write only attributes could 
> be easily added by just supplying "pushButtonNow :: Setter Button", albeit 
> breaking the := syntax - you'd have to say
> set b ["Hello" =: label, pushButtonNow]

Read-only or write-only attributes could be implemented by throwing an
error for prohibited operations. Read-only attributes could be
implemented by simply ignoring write operations.

> Here it is:
> 
> -- An attribute is a property of a widget. It knows how to set the
> -- and how to read the value of this property.
> data WidgetClass w => Attr a w = <abstract>

Using "WidgetClass" will confuse anyone who is used to Xt. With Xt, a
"WidgetClass" is a (pointer to a) record which describes the class
itself; the individual widgets have type "Widget". In traditional OO
terminology, "WidgetClass" is the metaclass of the "Widget" class.

Also, the above implies that attributes are tied to a specific type,
rather than to a class (including subclasses).

I don't know about GTK, but Xt and Qt both use an OO-style class
hierarchy. OTOH, different toolkits (and, in the case of Xt, widget
sets) will have differing hierarchies (e.g. for both Athena and Motif,
push buttons are a subclass of labels, but this isn't so for Qt).

> -- An example for a Button widget: The constructor has one
> -- mandatory argument.
> newButton :: Container -> [Setter Button] -> IO Button

1. This omits widget name, which should be mandatory.
2. Container should be a class rather than a type.

> -- The Button has at least this attribute.
> label :: Attr String Button

So do labels, toggle buttons. Is a label's label really different from
a button's label?

> -- This is one callback the Button provides. Note that you cannot
> -- attach any function at construction time or with the set
> -- function. The returned action is the unregister function.
> onClicked :: ButtonClass b => b -> IO () -> IO (IO ())

"Clicked" is likely to be an inappropriate name. E.g. several Motif
widget classes have an "activate" callback. For a push-button, this
may occur either as a result of clicking on a button, or using the
keyboard accelerator (Alt + underlined character), or moving the
keyboard focus to the button then pressing space. Either way, it's the
same callback.

Ditto for Windows, and probably for most other toolkits (except
Athena).

More importantly, most callbacks will need to take one or more
parameters which provide further information about the event. E.g. for
Motif's XmPushButton, the information passed to the activate callback
allows the callback to distinguish between single/double clicks. For
more complex widgets (e.g. text fields), substantially more
information may be passed.

We would need a CallbackData class in order to provide a generic
function for adding callback handling, e.g.

addCallback :: (Widget w, CallbackData d) => w -> CallbackIdentifier -> (w -> d -> IO ()) -> IO ()

Or even use dependent types, so that the data has to match the
specific callback.

-- 
Glynn Clements <glynn.clements@virgin.net>