[GUI] State, Attributes and Some basic widgets

Axel Simon A.Simon@ukc.ac.uk
Tue, 15 Apr 2003 21:54:47 +0100


On Tue, Apr 15, 2003 at 09:34:29PM +0100, Alastair Reid wrote:
> Since Haskell has a different type system from OO languages, we simply
> cannot do things the 'typical GUI toolkit' way.  Instead, we have to
> find a way to encode as much as possible of the foreign type system in
> Haskell's type system.
> 
> One way to do this is the one Wolfgang advocates: we provide a bunch
> of separate datatypes for each leaf node in the OO class hierarchy, we
> provide a class for each non-leaf node (or 'abstract class' if you
> prefer) in the OO class hierarchy and we use inheritance between the
> Haskell classes and instance declarations to encode the inheritance
> relations in the OO class hierarchy.  This approach suffers a bit from
> being tedious to specify all the instances you need for each datatype
> but otherwise works pretty well.

Manuel uses type classes to enforce the inheritance relationship.  I
construct these classes automatically for gtk2hs. I think this matches
very closely what Glynn and you propose. One question which I asked
earlier is: a) Shall the classes containt the widget's functionality as
well? (Or, alternatively: b) Shall we have a class for each attribute
(like "onActivate") and create instances for all widgets that implement
it.)

The type definition for a Button in gtk2hs looks like this (and as you 
might guess, it is generated automatically):

Cheers,
Axel.

-- ********************************************************* Button

newtype Button = Button (ForeignPtr (Button))

mkButton = Button
unButton (Button o) = o

class BinClass o => ButtonClass o where
  toButton   :: o -> Button
  fromButton :: Button -> o

instance ButtonClass Button where
  toButton   = id
  fromButton = id

instance BinClass Button where
  toBin   = mkBin.castForeignPtr.unButton
  fromBin = mkButton.castForeignPtr.unBin

instance ContainerClass Button where
  toContainer   = mkContainer.castForeignPtr.unButton
  fromContainer = mkButton.castForeignPtr.unContainer

instance WidgetClass Button where
  toWidget   = mkWidget.castForeignPtr.unButton
  fromWidget = mkButton.castForeignPtr.unWidget

instance ObjectClass Button where
  toObject   = mkObject.castForeignPtr.unButton
  fromObject = mkButton.castForeignPtr.unObject

instance GObjectClass Button where
  toGObject   = mkGObject.castForeignPtr.unButton
  fromGObject = mkButton.castForeignPtr.unGObject