[GUI] Towards a low level specification?

Axel Simon A.Simon@ukc.ac.uk
Thu, 20 Mar 2003 10:43:47 +0000


Sorry for the long mail, I had no time for a shorter one. (Goethe)

On Thu, Mar 20, 2003 at 01:29:26AM +0100, Vincenzo Ciancia wrote:
> Axel Simon <A.Simon@ukc.ac.uk> wrote:
> 
> >   Gtk uses a very similar approach in that each event can have several
> >   callbacks registered and you can remove each callback individually.
> >   So I think my proposal serves this 1:n correspondance
> 
> I can think of many other ways to solve the problem. And, besides, I can
> see many other ways to initialize, and access fields of, widgets and
> things that have properties, in general.
 Let's hear it :-). The MVar approach has surely disadvantages: In the 
low-level gtk2hs veneer you can say right now:

  sid <- button `onClicked` putStrLn "Hello"
  button2 `onClicked` disconnect sid

This code attaches a callback to the first button and disconnects it when 
the second button is pressed (probably a bonkers example). With the MVar 
approach we would need to write something like:

  remove <- newEmptyMVar
  button <- newButton [onOff click remove := putStrLn "Hello"]
  button2 <- newButton [on click := withMVar remove id]

This is surely a little clumsy. If the majority of removal functions for 
callbacks are done like this, then my approach is not really nice. If 
removal functions are usually stored in an MVar in the program state, then 
I think its ok.

> Now I play the role you played against me last week :) : if all the
> toolkits allow it, can we have function wich take no initializers, and
> provide get and set functions for attributes? Other approaches are
> implementable on top of this really weird interface.
 Ok, let me try to recover my argument: Having a mid-level API should 
enable the user to write applications concisely. Thus if a) passing a list 
of attributes to the constructor makes code shorter and b) we can agree on 
a design where advantages are clear and dominate, we should have it in 
CGA.

My impression was that the event/callback issue was a little religous. As 
such, the advantages where not too clear for everybody.

Maybe the same thing holds for the setting attribute issue.

[..]
> 
> Besides, I see a very clear distinction between what's low-level and
> what's mid-level:
> 
> - low level is everything that needs FFI and/or writing to handles to be
> implemented.
> 
> - mid level is everything that can be implemented in haskell, over the
> low level ground.
> 
> So, I ask to everybody: would it be right to provide a working low-level
> interface, in the IO monad, even if it sucks completely, call it "the
> CGA core", and ONLY THEN think about issues as initialization syntax and
> a nice way to handle local state? 
> 
> Note that this does not mean that we'll claim that our work is finished,
> when we have the core. Instead, we'll really focus on the mid-level, and
> produce a good one, before declaring the CGA as a standard; this is
> necessary IMHO.
 Clarification: What I meant by the "core" so far was the functionlity to 
set/get attributes, how to organize widgets with type classes, how to 
model callbacks/events, etc. To implement these issues we probably have to 
talk about what low-level functionality we have in our backends and how we 
would like the mid-level CGA to look like.

For all other stuff (set of widgets, their functionality, application
setup (MDI, SDI,..), window types,...) we can probably get away by just
defining the mid-level functions we think are sensible without explicitly
stating how the underlying IO actions are called. I.E. we only need to say 
we want

createButton :: [ButtonAttribute] -> IO Button
with the attributes clicked, label, ...

but not that this function calls these function

buttonNew :: IO Button
buttonSetLabel :: Button -> String -> IO ()
onClicked :: ButtonClass b => b -> IO () -> IO (ConnectId b)

since these are up to each backend implementation.

> Let's vote for this, here are the two alternatives
> 
> 1. to have at least a simple syntax wich is not like an assembly
> language is good, and comfortable even when writing the low-level stuff;
> so it's better to design some standard mid-level interface right now
> 
> 2. by designing a weird interface in the IO monad, similar to the ones
> we find in traditional imperative languages, we will produce the core
> much faster; it will be minimal and open to other implementation; also,
> people will have more time to think to nice syntaxen and the state
> handling issues; so it's better not to do any mid-level stuff right now.

 I hope to define the "core" as it appears in the poll document with 1)
supported by arguments on the level of 2). The rest of CGA will hopefully 
be defined in terms of 1).

If events and the synchronization points (the two issues again) a) 
make programming CGA easier and conciser and b) we all agree on an 
implementation then it should be in CGA.
Everytime we don't agree on b), I try to mediate by asking if we could 
implement the issue on top of other functionality.

Axel.