[GUI] Dynamic ... something

Wolfgang Thaller wolfgang.thaller@gmx.net
Sat, 12 Apr 2003 18:54:13 +0200


Glynn Clements wrote:

> Allowing fixed-coordinate layouts is an open invitation for people to
> write code which only works correctly on their system; they will just
> tweak the numbers until it looks correct with their preferences.

I agree that the use of fixed placement should be strongly discouraged.
I would want the feature to be in the CGA anyway, mainly for two 
reasons:
a) as a base to implement automatic layout on, at least for platforms 
that don't provide their own automatic layout features (Mac OS, Windows)
b) because it is really easy to implement - it would be very useful for 
testing in the early phases of CGA development.

> The easiest way to get both portability and native l&f is to use
> external interface definitions. The interface definitions themselves
> aren't remotely portable, but at least it keeps the non-portability
> out of the actual code.

I actually agree, but I think it shouldn't be the only way.
Personally, I'd be happy to use Apple's Interface Builder to draw the 
interface of my Haskell programs.
However, I'd sometimes prefer to have a slightly sub-optimal Mac 
version (interface created using automatic layout algorithms from the 
Mac backend of the CGA) than not to have a Mac version at all, which 
would mean I'd have to use the GTK or Motif versions via [local] X11 on 
my Mac (--> even less native look&feel).
Then, there's the issue of dynamically-generated interfaces - we need 
programmatical automatic placement in that case.

> For UIL, you also have to provide definitions for any attribute values
> which can't be specified inside a UIL file (e.g. pointers, callbacks).
> Basically, the UIL file uses symbolic names, and you provide a list of
> name/value pairs to map the names to specific values when loading the
> file.

Which brings us to another problem; the mechanisms for interfacing 
interface files with the rest of the program are vastly different:

Motif/UIL/UID: (just what I heard on this list, I really no nothing)
Each widget can be identified by its name.
Callbacks referenced from the interface file are specified using a 
name. When loading the interface, a name/value mapping has to be 
provided.
Other data (examples please... images?) may be provided in the same way

Windows Resource files:
Each widget can be identified by its numeric ID.
You can't define separate callbacks for different widgets; instead, you 
define one for the entire dialog, which gets passed, which can take 
decisions based on the clicked button's ID.
Only fixed layout is supported, no resizing.
Resizable windows like document windows are usually created 
programmatically.

Macintosh Carbon (nib files):
Each widget ("control") inside a window/dialog box has an ID that 
consists of a four-character-code and a numeric ID.
For each control, you can also set a four-character "command ID" that 
gets sent to the callback when e.g. a button is pressed.
Only fixed coordinates are supported, no resizing.
Resizable windows like document windows are usually created 
programmatically.

Macintosh Cocoa (nib files):
You usually don't identify individual widgets from the outside. 
Instead, you connect an objects "outlet" to the widget. When the nib 
file is loaded, the object is instantiated dynamically and a member 
variable is set to point to the widget.
Only fixed coordinates are supported, but you can specify how the 
widget should react if its container is resized (stretch, stay on left, 
stay on right, stay in center etc...).
Document windows are created from nib files, too (not programmatically).

I currently don't see how those differences can be reconciled without
a) requiring platform-specific code
b) sacrificing features
or c) both of the above :-(

None of the approaches need to be mutually exclusive, though:

1) Explicit placement
(should not be used directly except in some strange case that I just 
can't think of)
2) Platform-specific interface definition files
3) Dynamic layout

For 3), I'm thinking of a high-level approach.
Of course, there'd be the usual grid-based mechanisms (cf Java's 
GridBagLayout), but I'm also thinking of specialized layouts for 
special situations - like a "button bar" in a dialog box, where you 
just tell the layout manager which button is the OK button and which is 
the Cancel button and so on.
I'd implement this in Haskell, on top of 1); I'd tweak the algorithms 
separately for each platform. For platforms with good support for 
dynamic layout, we might be able to do it on top of "native" features.

> If you want native l&f, you have to redo the layout for each platform.
> If you try to impose a portable solution, you'll end up with something
> that doesn't have native l&f on anything. Even if all of the common
> platforms provided exactly the same layout interface, unless they also
> had identical style guides, you would need to re-implement the layout
> for each platform.

So let's not impose anything - but we might still want to provide it. 
Most style guide differences can probably be resolved by the right kind 
of abstraction (e.g. button ordering, sizing & spacing).
Maybe I'd develop my programs on the Mac, and then move them over to 
Motif and only manually redo the layout where it needs fixing. I'm sure 
that it's possible to get "perfect" platform-independent layout for 
simple forms...
(If it turns out to be absolutely impossible to create results that we 
can be happy with, we can still leave it out...)

Cheers,

Wolfgang