
Wolfgang Thaller wrote:
So allow me to try to summarize the discussion about dynamic layout:
We'll have one or more of the following (correct me if I left something out, or if I'm misrepresenting something):
For Xt (Athena, Motif), you have a choice of: 1. Programmatic creation of widgets with programmatic specification of layout attributes. 2. Programmatic creation of widgets with layout attributes taken from X resources. For Motif, you have some additional choices: 3. Creation of widgets from UID (compiled UIL) files, with layout attributes specified in the UIL/UID files. 4. Creation of widgets from UID (compiled UIL) files, with layout attributes taken from X resources. In all four cases, the set of available layout attributes depends upon the widget's parent (container). Some (e.g. XmRowColumn) have minimal or no layout attributes; others (e.g. XmForm) have extensive layout attributes. For XmForm, absolute positioning is just one possible option (effectively, the top/left attachments are to the edges of the parent, with offsets specified in pixels).
Something like: nib <- loadAppleNibFile_MAC "foo.nib" -- a nib file is a document created by Apple's Interface Builder and contains one or more dialogs dialog <- createDialogFromNib_MAC nib "MyDialog" If "MyDialog" doesn't refer to a dialog in the file, a runtime error occurs...
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.
What about making layout management a feature of a containter widget? When adding widgets to a FixedLayoutContainer, you'd have to specify the coordinates, when adding widgets to a GridLayoutContainer, you'd specify row & column, etc. We could start with just a FixedLayoutContainer (that's easy), and then we can go on and add "more intelligent" layout mechanisms.
Specifying fixed coordinates is likely to violate native look-and-feel (you have no idea what the default font is), and will break down if the application is customised (e.g. changing labels). 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.
Another, similar approach would be to make the "layout manager" an _attribute_ of a container widget (as is done in Java's AWT, if I remember correctly). Don't know if that has any advantages for our situation.
Java's AWT is a great way to write programs which are instantly
recognisable as "Java AWT" programs (i.e. instantly distinguishable
from "native" programs).
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.
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.
Of course, people may ultimately decide that native l&f is just too
much work, and abandon it. It's certainly an option. But, if native
l&f is abandoned, it should be a conscious decision, rather than a
accidental consequence of not realising what's involved until too
late. Also, it makes it less likely that the end result will actually
be the one-and-only UI library; if Haskell is around long enough,
eventually someone may want native l&f badly enough to implement a
library which provides it.
--
Glynn Clements