From: Duncan C. <dun...@wo...> - 2006-01-12 16:05:38
|
On Thu, 2006-01-12 at 15:18 +0000, Axel Simon wrote: > I think that objects like the TreeModels might best be implemented by > providing a structure that lives in C land and that is indeed a GObject. > The user can then fill out this skeleton with some stable pointers. I'd > be happy with that. that's the way the CustomStore works now, but providing an implementation of that requires some data that lives in Haskell land as well as the C object. For example: makeListStore :: [Column a] -> [a] -> IO TreeModel makeListStore rs xs = customStoreNew $ let size :: Word32 size = fromIntegral (length xs) rows = listArray (0, size - 1) xs cols = listArray (0, length rs - 1) rs in CustomStore { ... } This is ok because the rows array is static. I we want to make a modifiable store then we need to pass back to the user a wrapper around that Haskell data structure, eg: data ListStore a = ListStore { c_model :: TreeModel rows :: Sequence a, } makeListStore :: [Column a] -> [a] -> IO (ListStore a) Actually this gets us back to the point we discussed a few weeks ago about not wanting to have type parameterised widgets/GObjects like "ListStore a". ie we actually don't want to make (ListStore a) an instance of the TreeModelClass. So maybe it's all ok. :-) We can have either: makeListStore :: [Column a] -> [a] -> IO (ListStore a, TreeModel) or perhaps better: makeListStore :: [Column a] -> [a] -> IO (ListStore a) getListStoreModel :: ListStore a -> TreeModel > The only other point where I can see that a Haskell GObject could be > useful is if you implement your own widget on top of GtkDrawingArea and > pass that around as if it were a normal widget. > > [..bits written and deleted here...] > > I think your observation is a bit pessimistic. If I wanted to implement > my own widget, I should: > > - define a MyWidget newtype that contains a ForeignPtr, just as > DrawingArea is > - make it instance of DrawingArea, Widget, GtkObject, GObject > - on creation, add a new data member (by name, for example) that > contains a stable pointer to my data > - write my object methods that access this stable pointer for the > object's content. You mean store some private data in the GObject. Yeah, we could make it easier to do that. > I think this is certainly a viable route and, actually, the only route > if you want to actually implement upcasting: A Haskell data structure > that contains a DrawingArea is easily downcasted to the DrawingArea > (extract the DrawingArea member of the Haskell record). Yes. (except you've got upcasting & downcasting the wrong way round - or your and my class inheritance trees grow in opposite directions! :-) ) > However, > upcasting is nigh impossible since you'd have to wrap any given > DrawingArea into the Haskell record and fill out the fields. So, > although the DrawingArea-in-Haskell-record approach of extending the > DrawingArea is certainly useful in practise, you couldn't make such a > structure an instance of DrawingAreaClass. > To summarise: If you want to create a proper object in Haskell that > derives from GObject then you have to add a StablePtr to that GObject. > In that case you can use the default class mechanism to express > inheritance. Yes downcasting is impossible without the extra Haskell data being kept in the C object (in a StablePtr). I think it would be possible to do this mostly automatically if we wanted to. But actually because of the "no parameterised instances of GObjectClass" issue, I don't see the immediate need. Duncan |