Version française
Home     About     Download     Resources     Contact us    
Browse thread
Does LablTk have a future?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: skaller <skaller@u...>
Subject: Re: [Caml-list] Re: Feeding the OCaml GUI troll
On Fri, 2005-09-02 at 10:40 +0300, Ville-Pertti Keinonen wrote:
> On Thu, 2005-09-01 at 23:15 +1000, skaller wrote:
> 
> > I am. My idea is this: GET RID OF CALLBACKS.
> > The idea is to use (user space) threads instead.
> > 
> > The big problem with GUI's is that they're passive.
> > You write 'event handlers' and have to store the current
> > state manually. By control inverting the code, you can
> > just use a thread for each widget.
> 
> Have you actually done this in a GUI context, or do you just find it
> conceptually attractive?

I have done some brief experiments to check it can be
made to work .. but the real answer is no, it is only
a planned application (of Felix). But see below ..

> I've experimented with GUI concepts and event mechanisms in OCaml, and
> created an event mechanism that could relatively easily be used in a
> sort-of control inverted form by manually wrapping things into
> continuations.  I never ended up making use of that form of events for
> the actual low-level GUI functionality, because it always seemed easier
> to just use methods or attach callbacks to events and use explicit
> state. 

Yes, that seems likely for simpler low level things:
for example for a button (my example) clearly you just
need a boolean flag, which is pretty easy to maintain
manually.

However I *have* used the mechanism in a sophisticated embedded
environment, namely a telephony system.

We found, as above, that for some event handling,
callbacks were indeed better: some events like 
'phone call disconnected' are global, pervasive,
and in this case quite final.

Other events didn't fit so easily into this category.
Excuse brief explanation: the system used an asynchronous
real time data base. One task was to terminate a prepaid
phone call when the client's money ran out. In a place
like USA, where phone companies offer various deals,
and there are multiple time zones, the costing algorithm
can be quite complex -- especially if the client is
mobile (basically a recursive tree search with
pruning is required to find the minimum cost 'route')

To do this with hand written callback driven code is 
well nigh impossible. The algorithm is hard enough
written in a functional form with referential transparency
to help reason you have it right.

The fact the control inverted (event driven) form
is object oriented/procedural, yet equivalent to
a purely functional algorithm, makes mechanical
control inversion attractive -- but the utility
is only apparent in more complex examples.

>  Now that could simply be because I was sort-of porting a GUI
> library that I had written earlier (in C++ and Scheme) and I'm rather
> used to GUI mechanisms layered around inheritance (one of the few places
> where it actually seems natural to me).

I guess you start with simplistic procedural code, but
then find it is too hard to tailor and start using 
inheritance to help with that.

Unfortunately, a bit further down the track,
you again find it isn't good enough, and you need
much more dynamics -- and you have to switch
to delegation.

Further still, even that isn't dynamic enough,
and you start needing real message passing, that is,
posting events into the event queue as a means of
communicating between widgets.

The real question is, at this stage of sophistication,
whether you wouldn't be better off due to strong
static type checking, implementing stuff with functional
style instead: functional code can represent state too,
using closures.

I don't know the answer .. but I do know existing GUI's
are pretty bad. It is FAR too hard to get even simple
things to work, and hardly any GUI applications around
have any really high level functionality: the programmers
are struggling so hard to get really basic things to work.

> > For example for a button something like:
> > 
> > 	let rec wait_down () =
>   ...
> 
> > 	and wait_up () =
>   ...
> 
> > is purely functional: it uses the program counter
> > to maintain state, instead of a mutable state variable.
> 
> But consider that the state of a button isn't quite that simple.

The code was just an example of the style: for a more sophisticated
widget -- I mean lets go all the way and look at a tree widget,
an edit widget, or a canvas ... it isn't clear functional code
will be easier.

> Tracking the state explicitly isn't difficult 

No, not for a button. But for complex widgets it is.

Lets face it -- most programmers can't even get the mouse cursor
right. GQView, magnify/shrink with the mouse changes the mouse
from (+) to (-) when you next move the mouse .. which is plain
wrong (it should change as soon as you click to magnify or
shrink).

Many games .. mouse droppings (they got the double buffering
wrong).

So the fact is, programmers simply cannot manage trivial
state in a modern GUI correctly -- particularly they cannot
keep the user view of the state properly synchronised with
the internal state.

Interestingly I think Tk handles this quite well (it knows
when state is changed and re-renders the right things at
the right time automatically).

Windows is particularly BAD at some things, for example,
the tool used to edit the environment is utter rubbish:
PATH etc have very long string values and the dialog
box is small and fixed size .. this is just rubbish.

Another example: the ocamlbrowser is quite nice,
except it spawns top level windows left right and
centre, gets the size wrong, so every window has
to be adjusted. Any decent tool would allow you to spawn
those windows inside a pane or container of your choice:
modern 'Window managers' are just rubbish.

Sophisticated applications (eg Visual Studio) will give
you the choice .. but it is all hand programmed
for that particular application. I have designed a 
system called HWM (Hierarchical Window Manager) which
does away with that completely -- instead of a toolbar
you get a tree widget, which allows you to move windows
around in groups, and mutate their containers to any kind
you like (top level, panes, notebooks, etc). 

I have actually implemented this three separate times.
It relieves the programmer of the burned of hand coding
'mega-widgets' and leaves the organisation of widgets
up to the end user in a consistent way.

Of course .. this is a fairly radical concept .. the 
Open Source community would rather just copy Windows
and add minor improvements than bother to do any real
design work.

The real problem, IMHO, is C. You just cannot consider
new high level concepts for a GUI and implement them in C:
it is way too hard. 

Ocaml offers opportunities to do much better .. but there
is no point just copying existing GUIs: we already have
LablTk and LablGtk, which provide standard functionality
rewrapped more nicely. If we're going to do a real GUI
designed to take advantage of an advanced functional
programming language, we need to do a whole lot better
than what we already have .. and I do not see how to do this
without a lot of design work.

We do NOT want something with the same look and feel as
existing GUIs. They suck. But we have to have something
much better to be convincing .. do you remember the days
before Drag-and-Drop existed?

IMHO the *key* problem with GUI's -- and why real (TM) developers
hate using them -- is the lack of automation: unix script 
sucks, but it does provide automation. If we're going to make
a new GUI it has to have full automation capability.

The only way I can think of to do that is to base the 
core components of the GUI on Category Theory -- for example
have 'product' widgets and 'sum' widgets which represent
a collection and a set of alternatives, respectively,
and a standard way to combine them graphically.

-- 
John Skaller <skaller at users dot sourceforge dot net>