[GUI] I love GIO.

Daan Leijen daanleijen@xs4all.nl
Wed, 12 Feb 2003 21:14:34 +0100


Axel Simon wrote:
>
> So you're now doing a binding to wxWindows. May I criticise?!
> 
> wxWindows tries to give a native look by using the native API. It seems to 
> do a good job. But when it comes to native feel, I wonder if this 
> full-fledged API can abstract away the semantic differences of the 
> platforms. I guess there is always need for a serious application to 
> implement certain bits of the GUI directly with the native API to bridge 
> this semantic gap. Can you use wxWindows for the standard GUI stuff and 
> still use the native API for some functionality? If yes, then this is what 
> - I think - we are aiming for. In that case I might consider dumping my 
> gtk2hs binding and help you with a binding to wxWindows.

I am not a wxWindows expert but I got the impression that very serious
applications were written in wxWindows and that it may thus be more than
enough for the humble Haskell programmer.

I also saw some definitions that were commented with "(only has effect on platform XXX)"
and some functions that gave access to a platform specific "handle".

> Why not the other extreme route: Having one class for each widget? The 
> name overlap is minimal I think and it is much easier to understand.

You are right. The drawback is that certain (object) classes have the same methods
and you would get into trouble if you try to generate one (type) class for each widget
(kind) class. However, I found out that attributes weren't regular enough for 
automatic generation and I am thinking about writing them by hand, in which
case your proposed approach is probably better.
 
> If let wxWindows handle the applications state (via StablePtr), how are 
> you going to make that type safe? Mulit-parameter classes? I think 
> the common GUI API should be in Haskell 98.

You misunderstood me. The wxWindows C++ objects maintain state. If I can
set something, I can always also get the value back. With Port this is not always
the case and you have to 'remember' an attribute value also on the haskell side
with a mutable variable.  This means that with wxWindows I can get away with
just using plain stable pointers to C++ objects without any mutable variables in
Haskell.

> One point that came up in our Departmental FP group was that the way 
> Object I/O identifies objects is superior to GIOs. They create an 
> identifier with a special monadic function rId. The you construct an 
> algebraic data type which specifies you GUI. GIO on the otherhand uses 
> functions to create widgets. You use these widgets values to pass them to 
> other widgets (e.g. containers). Note that in both settings it is possible 
> to put one button into two different container. But only in the Object I/O 
> approach this can easily be detected (you keep all created rIds in an 
> array and see if they have been used yet). In GIO you would need to 
> traverse the whole widget tree of all windows to determine if a button is 
> already inserted somewhere else.

I wouldn't say superior as both are implementable in terms of each other.
It is just another approach. As Krasimir already said, the only point where
GIO can go wrong is when trying to lay out a button in a widget that is not
its parent. This can also easily be detected at runtime (check if the parent
is the current widget) -- there is no need to traverse the widget trees.

Furthermore, I really like the strong typed connection between a widget and
a haskell identifier. The real drawbacks are in my opinion:
1) the need to specifiy a parent (w) when creating a control  (ie.  b <- button [] w)
   this hinders abstraction.
2) layout is not statically checkable, you can put controls in the wrong window.

Now, ObjectIO "solves" these above problems by having an algebraic data type
that describes the gui and layout.  This structure is than interpreted by the parent
that creates the controls and lays them out (using GIO like calls). To let controls
communicate with each other, you are forced to use generated Id's instead of
normal identifiers.

By doing that, you also loose things:  you need to lump all control attributes together
in one big data type for example. For libraries as wxWindows this leads to a really
huge data type. Or you can specify attributes that are ignored / not applicable for a
certain window/control.

Now, I don't know yet the correct solution for this dilemma. Krasimir uses
an ObjectIO like approach of specifying the GUI but his function returns
a list of identifiers for each element. By binding them lazily, the controls can
refer to each other before being actually created. It goes something like this:

>  ~(b1 :+: b2)  <- (button1 <<< button2)

All the best,    
  Daan.


> So much for now,
> Axel.
> 
> _______________________________________________
> GUI mailing list
> GUI@haskell.org
> http://www.haskell.org/mailman/listinfo/gui
> 
>