[GUI] Another RFC on setting and getting.

Glynn Clements glynn.clements@virgin.net
Tue, 8 Apr 2003 08:20:29 +0100


David Sankel wrote:

> > 1. Records (with named fields) would be preferable
> > to tuples; Some
> > callbacks get passed a significant amount of data.
> 
> Can you give an example where a standard widget would
> pass a significant amount of data?

1. For Motif's XmText and XmTextField widgets, XmNlosingFocusCallback,
XmNmodifyVerifyCallback, and XmNmotionVerifyCallback are passed:

       typedef struct
       {
               int reason;
               XEvent * event;
               Boolean doit;
               XmTextPosition currInsert, newInsert;
               XmTextPosition startPos, endPos;
               XmTextBlock text;
       } XmTextVerifyCallbackStruct, *XmTextVerifyPtr;

2. For Motif's XmList widget, various callbacks are passed:

       typedef struct
       {
               int reason;
               XEvent *event;
               XmString item;
               int item_length;
               int item_position;
               XmString *selected_items;
               int selected_item_count;
               int *selected_item_positions;
               char selection_type;
               unsigned char auto_selection_type;
       } XmListCallbackStruct;

3. For several Motif widgets, XmNdestinationCallback is passed:

       typedef struct
       {
               int reason;
               XEvent  *event;
               Atom selection;
               XtEnum operation;
               int flags;
               XtPointer transfer_id;
               XtPointer destination_data;
               XtPointer location_data;
               Time time;
       } XmDestinationCallbackStruct;

> > 2. This approach requires a different function for
> > each type of
> > callback. I would prefer a single polymorphic
> > addCallback function.
> 
> This is again making runtime errors into what could
> have been compile time errors.  I think this is reason
> enough not to do it this way.

To some degree, that's inevitable if you wish to expose the full
functionality of Xt. Xt's design is inherently open-ended. E.g. a core
set of generalised functions are used for all widget and attribute
types, rather than each widget having a separate creation function,
each attribute having separate get/set functions, coupled with the use
of strings as keys and the ability to obtain widget-class descriptions
at run time.

This aspect can be important if widget hierarchies are written in UIL
and loaded at run-time.

Having said that, fixing a subset of functionality at compile-time
probably wouldn't impact most applications (so long as the subset
itself is adequate). I doubt that anyone considers interface builders
or an editres clone to be a priority.

Basically, the main reason I joined this list was to try to ensure
that any compromises were made after full consideration of the facts. 
I've seen too many cases where supposedly generic interfaces were
based upon an over-simplified model (toolkits which assume that issues
related to X's client-server model can be ignored; wxWindows not using
widget names, resulting in the Motif implementation sucking badly;
that sort of thing).

Aside:

More generally (and getting somewhat off-topic for this list), "open"
interfaces are an area where static typing is problematic. For another
example, consider the issue of writing a Haskell binding for the BSD
sockets API.

In the underlying API, socket addresses are an abstract type. The
functions refer to addresses via a pointer/length pair; the only thing
that's known about the data is that the first two bytes indicate the
family. The set of valid families isn't known at compile time; with a
modular OS kernel, a new socket family could come into existence at
any time.

While the merits of static versus dynamic interfaces can be discussed
ad nauseum, when it comes to interfacing to existing libraries,
dynamic, open-ended interfaces do exist.

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