On Wed, 12 Dec 2007 15:36:26 +0100, Ken Tilton kennytilton@optonline.net wrote:
Ken Tilton wrote:
Ken Tilton wrote:
Peter Hildebrandt wrote:
OK, now that I am up to speed, let's go back to your original query.
Say, I have a model M that depends on the structure of a family tree. One of M's slots is therefore depending on the root of the family tree: (c? root). However, I want M to know about changes in the family tree, like, say, when a child or grandchild is added. Apparently cells (at least the cells_2.0 branch required by cells-gtk) does not broadcast change messages to the parents of a node (which I guess is the right thing in 99% of the cases).
What's the best way to deal with that?
(i) Is there some mechanism for this purpose present in cells? Or (ii) Do I roll my own special case solution? Or (iii) Is it worthwhile to build some general purpose solution to this problem?
My approach towards (ii) (I haven't coded anything yet, waiting for you comments) would be something like building an observer tree each node of which observes one node in the family tree. Something like this:
- Design a tiny tree observer model ("tto"?), suited to observing
one family node (defmodel tty (family) (observed observed-kids reports-to))
- Every tto knows about the parent model (M from above) and does the
right thing when it sees a change (say, call a closure)
- If the observed nodes has kids, it instantiates tto kids of its own
to match the kids of the observed tree (def-c-output observed ((self tto)) (make-tto :observed (c? new-value) :observed-kids (c? (kids new-value))) (setf (kids self) (mapcar (lambda (kid) (make-tto :observed (c? kid) :observed-kids (c? (kids kid)))) (kids new-value) ...) (def-c-output observed-kids ((self tto)) ...)
- Changing the root slot in M results in the instantiation of a tto
for the root
I guess that would work ... but I feel there must be a more elegant solution.
Roughly (cuz of rough recall of Cells2): (defmodel family-observer (family) ;; we'll use the "md-value" slot for the observed () (:default-initargs :kids (c? (the-kids (bwhen (o (^md-value self)) ;; not sure why not (loop for k in (^kids o) collecting (let ((this-k k)) ;; loop is weird (make-instance 'family-observer :md-value this-k))))))) That handles rows in/out.
Left unsaid was that you need an observer specialized on family-observer to relay changes to the Gtk side.
Ah, I get it. Would the following do the trick?
(def-c-observer kids ((self f-o)) (mapcar #'gtk-forget-about-and delete-that-row old-value) (mapcar #'not-to-be old-value)) ;; would i need that?
Help with this one is really appreciated, because I feel I have never quite understood how to handle making instances in a cells slot properly (I how to clean up properly).
As for individual values, well, I guess you generalize the handling of kids so it is just another slot-value. Changes to kids add/remove rows, changes to other things set values within a row. You know you need the kids handled, so what you might build that in and then have some macrology write the defmodel for custom subclasses of f-o: (def-family-observer my-tree (<def options?>) slot-1 slot-2)
Left unsaid is that def-family-observer expands into:
(defmodel my-tree (family-observer) <slot defs for slot-1 and slot-2> (:default-initargs :slot-1 (c? (slot-1 (md-value self))) :slot-2 <same>))
...and observers for slot-1 and slot-2 specialized on my-tree to relay changes to gtk.
Cool. Gotta love lisp, macros, and cells. I wonder how many lines of C that would make.
As to the current status, I'm messing with CFFI to get some more bookkeeping deferred to the GTK side. Once you get started there's a function of everything :)
Peter
kt