[GUI] Re: Know you backends

Daan Leijen daanleijen@xs4all.nl
Thu, 30 Jan 2003 14:32:50 +0100


Dear Axel,

> > I am also in favor of a medium level GUI interface. If I gave another
> > impression, that is my fault.
> Well, Ports is very low level like gtk2hs, since it is merely a wrapper
> around the C functions of HToolkit.

Well, the Port library is still medium-level. For example, the call "createWindow :: IO
WindowHandle",
basically creates a window with a working event loop, default handlers, a canvas,
automatic scroll bars and a seperate world and view domain. It basically provides
the core-functionality needed for ObjectIO (or something) but no utility functions
type safety, or abstraction.

> but if the Clean low level layer (L) which is written in C was
> portable, why don't we use that layer directly? Why did Krasismir start
> with HToolkit?

That is a good question. Personally, I would have preferred to see a GTK port
of the low-level layer of Clean  This would also allow us to work together
with the Clean people, they have an excellent compiler and lots of experience with
GUI's, and it could foster more exchange of knowledge between both communities.

Maybe Krasimir can tell us more about the issues involved?

(However, I can also live with Port since it seems much smaller and more tractable than the Clean
layer.)

This actually brings me to another issue I have been wondering about.
Why don't we use the GTK library as our portable GUI library directly?
I may have missed some discussions about this, but if it is a really portable
library, we can use the fruits of their labor. (Of course, it does need to
give a native look and fool, I wonder whether GTK does that?)

> I do not like the evolutionary approach. It will lead to an API which
> changes a lot.

Well, we both started out as amoebes but evolutionized into beings that use
electrical signals to exchange opinions about how to create specific patterns on
cathode ray tubes :-)


But seriously. We are trying to create a medium-level interface. The Port
approach is to create that using two layers: one core medium-level interface
(Port) and a convenience layer on top of that, using abstraction, overloading
etc (GIO/Htoolkit). The advantage is off course that more work is shared
and less work is needed for a different platform. Furthermore, the design of the
convenience layer is seperated from the implementation of the core functionality.
This is more important than it looks -- I think many truly useful libraries have
failed because they didn't have this distinction. This made it too hard to port
the library since there were too many dependencies on the platform. I think
this happened for example with TkGofer and Haggis  (still a wonderfully
complete and documented! library)

The disadvantage might be that Port is too low-level to bind to the GTK+HS
binding but I don't think that this is the case. Maybe you can say more
about this later.

> And the reason I'd like to have (A) as the common layer is:
> - We could both put an Object I/O layer on top of our libraries. If we use
> the same core functionality, it would enable people to easily migrate
> their applications from one specific backend to the common API.


The other approach, that you are proposing, is to define just one medium
level interface (with abstraction and all) and to implement backends for
each platform directly. The advantage is that it probably easier to support
more backends. The disadavantage is that you need to do more work
for a port.

However, it is not yet clear how that level should look like. We could take
the ObjectIO interface as our layer but I would not recommend that.
Note, this is not a critique on the ObjectIO library, I highly respect the work
of the Clean people, and Peter van Achten in particular. However, the Haskell
ObjectIO interface should be heavily revised to fit better in the style of Haskell.
Right now, it is still influenced by the non-monadic uniqueness style of Clean.
For example, the generation of identifiers (openId) is quit unsafe. In the Haskell
tradition we would use a monadic bind to name widgets.  ie.

>  w <- window []

instead of

>   w <- openId
>   openWindow ... [ WindowId w, ...]

Other things are the widget attributes that are specified using constructors. A more Haskellish
style
would use function names instead of constructors (as to be able to abstract from them) and use type
classes for grouping them (as to prevent using illegal attributes on a certain widget). i.e.

>  w <- window [title =: "My window" ]

instead of

>   w <- openId
>   openWindow ... [ WindowId w,  WindowTitle w...]

This is basically what I am trying to do in the GIO library. However, even than, there
are still tons of other design decisions to make, I wonder whether consensus can ever
be reached.

All the best,
    Daan.

ps. I am quite curious about what you think of Port. If it is high-level enough, it
may serve the role of a core-functionality interface and you could create a
port layer on top of gtk2hs.  You can browse the interface directly at:
http://htoolkit.sourceforge.net