[GUI] Class/Object Hierarchy

David Sankel camio@yahoo.com
Sat, 3 May 2003 14:06:06 -0700 (PDT)


--- Wolfgang Thaller <wolfgang.thaller@gmx.net> wrote:
> 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

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.  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