[GUI] Are windows just ordinary widgets?

Wolfgang Thaller wolfgang.thaller@gmx.net
Wed, 30 Apr 2003 23:42:55 +0200


Axel Simon wrote:
> IMHO the classes should just reflect the object hierarchy. If we have 
> e.g.
>
> class Button b where...
> class ToggleButton b where...
> instance Button ToggleButton where...
>
> then we can have the simple function
>
> onActivate :: Button b => b -> IO () -> IO ()
>
> and use it with ToggleButton as well (but not with a plain Widget or
> anything on the other branches of the tree). Having onActivate as a 
> class
> member doesn't give any improvement in type safety, is less efficient
> (bigger dictionaries) and doesn't lend itself to automatic creation of
> this type hierarchy.
>
> Axel.

I'm no longer entirely sure what we are talking about. What is "the 
object hierarchy"?

Could somebody who has an opinion on these issues knock up a concrete 
example; I'm not thinking of code, just some class declarations and 
signatures...

Here's a summary of what's in the FLTK-based example that David Sankel 
posted a while ago. I've added some comments.

class IsWidget a where
	toWidget :: a -> IO Widget

data Widget
instance IsWidget Widget

class HasOnActivate a where
   doOnActivate :: a -> IO () -> IO( IO() )

class HasTitle w where
   title :: Attr w String

-- This should be left to layout management:
class HasPosition w where
   position :: Attr w (Int,Int)

class HasSize w where
   size :: Attr w (Int,Int)

-- The following two are not possible, because of some toolkits' 
inability to reparent widgets after creation:

class HasAddChild a where
	addChild :: IsWidget b => a -> b -> IO ()
class HasChildren w ehere
	children :: Attr w [Widget]

-- ===

data Window
mkWindow :: [Prop Window] -> IO Window

instance IsWidget window
instance HasAddChild window
instance HasChildren window
visible :: Attr Window Bool

-- ===

data Button
mkButton :: [Prop Button] -> IO Button

instance IsWidget Button
instance HasTitle Button
instance HasOnActivate Button
instance HasPosition Button
instance HasSize Button

-- ===
-- The whole "Box" widget should probably be replaced by different 
kinds of boxes
-- that do different kinds of layout.

data Box
mkBox :: [Prop Box] -> IO Box

instance IsWidget Box
instance HasTitle Box -- <= it seems that in fltk, a box is more than 
just a simple container....
instance HasPosition Box
instance HasSize Box

-- ===

Some more notes:
If we want to implement a dynamic layout manager in Haskell for 
platforms that don't support that natively,
we will need a way to query things like minimum size when we have just 
values of some general type
(like Widget, though I already suggesting having a generic type that 
only includes all widgets _except_ windows).
The current "CGA example" doesn't provide that.
Also, the CGA example currently has completely separate code for the 
"HasSize" instances for Buttons and Boxes; but in the end, they both 
call the same virtual member function on a C++ object. There should be 
a way for backend implementors to avoid that needless duplication of 
work.

Cheers,

Wolfgang