
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