
--- Wolfgang Thaller
So what have we already agreed on? 1) There will be a datatype Window
okay
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. As for menu items, these seem to be more of an attribute of a menubar than a widget itself. This also simplifies things. I think we simply need Windows and Widgets.
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.
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)
5) For a particular widget type Foo, we will have 5a) data Foo
okay
5b) instance IsPane Foo
I would prefer IsWidget
5c) newFoo :: Container c => c -> [Prop Foo] -> IO Foo
From a programmer's perspective, this limits options. The main arguments for this is the implementation
I do not like passing the parent to the constructor. details for certain toolkits would be hard. I earnestly think this is worth it though. 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. 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). 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. 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.
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. 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. See how simple the following code is: a1 <- newHBox [ children := [ ButtonA, ButtonB ] ] a2 <- newHBox [ children := [ ButtonC, ButtonD ] ] b <- newVBox [ children := [ label1, a1, label2, a2 ]] return b Since they are also easier to implement on platforms that do not have Grids . . . these are likely to be the first two layout candidates I'll put in the fltk implementation for critique.
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.
7) Below the "Pane" type and class, we'll try to keep the hierarchy flat (perhaps even absolutely flat)
I think that for now, we should keep it entirely flat with Windows and Widgets.
9) Do we prefer to use a) too many type classes, i.e. a HasFoo class even when there's only one widget that supports foo, or do we rather want to risk having b) too few type classes, i.e. making foo a plain function when we may later add another widget that supports the exact same foo?
I agree that performance costs are negligible. As far as namespace pollution goes . . . it seems to be negligible as well. Why would someone use a gui library with a title attribute and also really want the class HasTitle as well? It seems that using Has* classes will promote a common standard for naming overloaded haskell functions. Using the Has* classes also allows for unforeseen uses of CGA for custom widget types. For the next version of CGA-example I think I'll implement a few different ways of thinking. One may then try coding in the different versions and come to a conclusion on which is easiest. If this is to be widely used, the user (not the implementor) needs to be our target audience. David J. Sankel