[GUI] Class/Object Hierarchy

Wolfgang Thaller wolfgang.thaller@gmx.net
Sun, 4 May 2003 00:33:54 +0200


>> 2) There will be a datatype Pane
>
> I don't think we need this datatype.  Since Windows
> are not going to be widgets, we simply need Widgets
> and Windows.

This is simply a difference in terminology.
I was avoiding the term "Widget" because many people are used to 
thinking "Windows are Widgets". Most toolkits (all that I can think of) 
that use the term "widget" follow this model, and most toolkits (again, 
all that I know) that don't follow the window=widget philosophy use 
different terms. But in fact I don't care about how to call it.

> As for menu items, these seem to be more of an
> attribute of a menubar than a widget itself.  This
> also simplifies things.

Probably an attribute of a menu or menu bar, perhaps an object of their 
own, but definitely not a widget. Also, a menu bar is not a widget 
because it's not necessarily inside a window.

>> 3) ... along with a class IsPane (or PaneClass or
>> ...)
>> 	class IsPane p where
>> 		toPane :: p -> Pane
>
> This is similar to the IsWidget thing which I agree
> too.

It's the same thing, by a different name.

>> 4) There will be a class Container
>> 	class Container c where
>> 		-- member functions to be determined
>> And we'll have
>> 4a) instance Container Window
>> 4b) instance Container GridBox
>
> From a programmers perspective, having a Container
> class is of little or no use.  This is especially true
> since each container might have a different addChild
> function. (see more comments below)

Yes, if we use specialized addChild functions, we can forget about the 
class.

>> 5c) newFoo :: Container c => c -> [Prop Foo] -> IO
>> Foo
>
> I do not like passing the parent to the constructor.
> From a programmer's perspective, this limits options.
> The main arguments for this is the implementation
> details for certain toolkits would be hard.  I
> earnestly think this is worth it though.

I earnestly think it isn't :-).

>  There are
> two ways to implement this:
>
> 1) Try to work around it on the C side of things.
> Maybe one could derive a parent that doesn't show
> children.

That's not possible. The main limitation of Carbon and Motif is not 
that you have to specify the parent at widget creation; the problem is 
that you cannot change the parent afterwards (Xt) or that you cannot 
move a widget to a different window afterwards (Carbon).
If we put newly-created widgets in some container where they are 
invisible, they'll stay there forever :-( .

> 2) On the haskell side of things, all attributes and
> RO variables must be mirrored.  This would be easy for
> most attributes (since once the standard is complete,
> it would be easy to create a generator for most of the
> work).

Yes, but besides the obvious doubling of work, it would have one more 
disadvantage.
It would make it _very_ hard to allow other native widgets to be 
wrapped for use with CGA.
I would like to be able to create some widgets with platform-specific 
functionality, and then
manipulate it with CGA functions.
If those CGA functions insist on moving widgets to different windows, 
the CGA implementation will have to be able to read out _all possible 
attributes_ of _all possible widget types_ (even those not directly 
supported by the CGA) and recreate the native widget elsewhere. 
Definitely not possible, at least not for Carbon.
But I'd really really like to have that feature...

> I realize that smooth implementations is a strong goal
> for this project, but this is a really large chunk of
> logical and grammatical functionality we are
> sacrificing here.

Being able to just "cast" a native widget to a CGA widget is important 
functionality, too.

> I think my previous post which talks about eliminating
> Windows deserves some serious thought.  Perhaps, once
> implemented, it can be critiqued for its merits
> instead of discarded for to its originality.

You could of course provide an example in order to convince me and 
everybody else. But for now, I really fail to see the advantage. A 
Window is a real thing, that I want to be able to create and set 
attributes of. Why should it be automated away (at great implementation 
cost, because that really doesn't fit with any backend, and it doesn't 
fit at all with some backends)?
What would we gain by eliminating Windows from the API?

>> 6) GridBox is a layout container that works like
>> Gtk's Table, Java's
>> GridBagLayout and Tk's grid.
>> It should be implemented using Gtk's Table for Gtk,
>> and implemented in
>> Haskell for other platforms.
>
> My guess is that these different grid layouts have
> different math behind them.  Since there will need to
> be at least one Haskell implementation, we might as
> well use it for all of them to enforce
> standardization.

They are so similar that you can use all of them for some time without 
noticing any differences; also, of the three, Gtk is the only one we 
support directly, so why not use Gtk's table?
But of course, if our own implementation turns out to be better if we 
use slightly different maths, then I have no problem with that, either.

> I also strongly support use of HBox's and VBox's.  For
> hand written programs, they are of great use in
> organization of a gui.

As are GridBoxes. I have never used HBoxes and VBoxes myself, but they 
look like they can be easily implemented on top of GridBoxes, so if 
we're going to implement GridBoxes anyway, H/VBoxes are practically 
free. I see no reason not to include them if you want them.
HBoxes and VBoxes are not completely general, and I think grids are 
better suited to UI builders, so I do insist on putting grids in sooner 
or later.

>> We have
>> 6a) instance IsPane GridBox
>> 6b) instance Container GridBox
>
> Again, I only see a need for
>
> instance IsWidget GridBox
>
>> 6c) Layout constraints can be set using attributes:
>> column :: IsPane p => Attr (GridBox, p) Int
>> (and more attributes as required for a grid layout
>> algorithm)
>>
>> 	set (box,button) [column =: 1, row =: 1]
>
> Compared to
>
> addToGrid theGrid 1 1 theButton
>
> the above code lacks in readability and intuitiveness
> IMHO.

But row and column are not the only attributes; I just used the default 
values for the others in the above example.
The attributes provided by Gtk's table are, IIRC, row, column, row 
span, column span; Boolean attributes X expand, Y expand, X fill, Y 
fill, X shrink and Y shrink (though I haven't yet figured out what the 
"shrink" attributes really do in Gtk...).
Those are more optional attributes than can be managed using 'Maybe' 
parameters to an addToGrid function, so I tried to use attributes.

Also, if we provide a "FixedPlacementBox" (in order to implement other 
layout algorithms on top of it), we would have attributes that we would 
want to be able to change after the fact, when recalculating the layout 
due to window resizing. For that, the above "set" command looks 
relatively practical and intuitive. There might be better solutions 
though, only I wasn't yet able to think of them.

Cheers,
	Wolfgang