[cells-gtk-devel] Re: [cells-devel] Something like a def-family-observer?
Peter Hildebrandt
peter.hildebrandt at gmail.com
Wed Dec 12 03:21:46 UTC 2007
>
> OK, I understand. You are right, we want the tree-view to update
> automatically as the model changes, by which I mean either the
> population of the model or the value of a displayed slot of a node of
> the model, and normally this is how my GUIs work. It should be easy to
> get this in cells-gtk.
Thanks for the reassuring words. Sounds like we're in for some fun :-)
> I may have to build Cells-gtk. Possibly you have missed some existing
> mechanism in cells-gtk, so I have CCed that list. Or possibly the
Well, I got editing "cells" in the treeview through the gui to work in
cells-gtk (which was not supported so far). Thanks to that excercise I
know the tree-view code in cells-gtk pretty much inside out. I don't
think I missed something.
> cells-gtk tree-view got implemented with a static model in mind and it
> is merely time to break that assumption. No big deal, assuming GTk's API
> has the chops (which I wager it does).
You're exactly right. Cells-gtk is only prepared to deal with fully
replacing the lisp side of the model. All the code for rebuilding the
model on the gtk-side is triggered from the def-c-observer on the roots
slot. So either you have something simple like a list there (and
everytime you change it the observer rebuilds the whole model), or you
have something complex like a family (and it only gets rebuilt when you
setf that slot)
The GTK trieview OTOH is built on top of a dynamic model. There is all
the bits and pieces to do pretty much anything with that model. I've used
this tutorial so far:
http://scentric.net/tutorial/treeview-tutorial.html
The API is here:
http://library.gnome.org/devel/gtk/2.11/GtkTreeStore.html
> A question is how much work gets done on the Lisp side. Do we end up
> with one Lisp widget instance for each observed row? Better yet, for
> each field of each row? ie, the lisp tree-view runs down the model
> rooted in "roots" looking for kids of kids and then...
Not at this point. The current cells-gtk has nothing more fine grained
than the tree-store/tree-model whatever they call it. The rows and fields
are all assembled "on the fly".
But -- this is what I had in mind.
> hmmm, maybe not, and it looks like I better build Cells-gtk.
Keep in mind that it needs the "cells_2.0" branch. This is not in CVS but
part of the release on the website. Also, at least for me (SBCL/linux)
there
was a bug in gtk-app.lisp, resulting in a crash when closing an
application. Line 124 reads
(loop while (> (gtk-main-level) 0) do (gtk-main-quit))
but should be
(dotimes (i (gtk-main-level)) (gtk-main-quit))
> Normally what I do is mirror each thingy on the C side with a thingy on
> Lisp side, so there would be tree-view and then tree-view-row and maybe
> tree-view-row-field (or tree-view-cell in spreadsheet-ese). To make
> things super-flexible, I then make those types parameterizable, so I can
> make a custom tree-view-cell (by subclassing tree-view-cell) and then
> specify to tree-view that it should use that subclass as it is
> traversing my data model building up the Lisp tree-view.
Sounds great. So I am not the only dreamer out here :)
> At this point, of course, on the Lisp side anyway I can "see" cells-wise
> everything that is happening, including tree insertion/deletions and
> changes to slot values of model nodes. The next question is how to tell
> GTk.
Exactly, that is what I had in mind when I outlined that "tto" strategy.
Have generic model embody the functionality of observing lisp and updating
C, and then subclass it for the various cases.
As a side effect this will make handling user input a lot nicer: The bits
linking the clos slots to the tree-view cells might know about the inverse
function and thus propagate a setf back, i.e.
User changes something
=> tree-view widget sends setf to the corresponding connector
=> connector setf's the corresponding slot in the observed model
=> that gets propagated into the connector
=> the connector tells GTK about the change
> Does Gtk give us the granularity to operate on the tree view, ie, does
> it allow us to say "remove this row" or change this field of this row to
> show this new value ("My child")? I think you said yes to this in your
> prior note.
Yes, it does (see pointers above).
> If so, the next question is if we have done the FFI for those bits of
> the API. :)
Mostly, I'd say. cells-gtk/gtk-ffi has append/insert functions and most
of the path/iter stuff to locate items. A function for setting values is
also there. What's left is removing stuff. Shouldn't be too hard.
> I'll stop here since I am just collecting info, but rest assured this is
> normal stuff and if the GTk API offers the hooks we should have no
> problem getting information to flow from the lisp side to Gtk, using the
> ideas hinted at above.
Cool. I'm looking forward to it.
Cheers,
Peter
> kt
>
>
>
>> So I came up with the idea to make the interface to the tree-view a
>> tree of cells, so that in effect for every box that is displayed in
>> the treeview there is a dependent cell in the treeview (Instead of one
>> cell connecting to the kids of the root).
>> One way to do this would be to have an observer object
>> (defmodel tto () ((obs :accessor obs :initarg :obs)
>> (corresponding-point-in-gtk))
>> (def-c-output obs ((self tto))
>> (call-gtk-and-set corresponding-point-in-gtk new-value))
>> Then we would make six of these, two per node (name and age) when
>> roots is assigned:
>> (def-c-output roots ((self tree-view))
>> (mapcar (lambda (nd) (make-instance 'tto :obs (c? (md-name nd))
>> :corresponding... ...)) (roots self))
>> ;; of course we'll have to recurse into the kids and the names of
>> the accessors
>> ;; are supplied somewhere to the treeview etc.
>> Additionally we'd have some sort of structure observer that listens on
>> the kids of every node (here three for three nodes) and reacts to
>> changes by adding/deleting rows to the tree-view. Additionally it'd
>> have to create/remove tto's to listen to the slots of new nodes or
>> stop listening to removed nodes.
>> Another option would be what I dubbed the "family-observer": Some
>> piece of magic that gets notified when any slot in a model or any of
>> its decendents gets modified. The notification would idealy include
>> the modified node, the modified slot, the new-value and a path from
>> the root to the node (could be a closure, (lambda (n) (nth 2 (nth 3
>> (nth 0 (kids n] => (lambda root) is the modified node, or just a list
>> '(0 3 2)). That family observer could then take this
>> notification/message and do the appropriate action.
>> I do not understand cells enough to judge whether this would even be
>> possible. So maybe there is something, some instance where all state
>> changes get passed through, that could filter out the ones going to
>> root or its descendents, maybe not.
>> Well, I hope it's clearer now what I wish to do.
>> In reply to your comments:
>> On Tue, 11 Dec 2007 21:03:39 +0100, Ken Tilton
>> <kennytilton at optonline.net> wrote:
>>
>>> More below, just retro-inserting notes: normally in /my/ work the
>>> parent slot is not even a Cell, but I /have/ done that a couple of
>>> times on certain subclasses of Family and it did work.
>> Yeah, thanks for pointing that out. I got that confused from time to
>> time and was wondering why a (c? parent) does not learn about (kids
>> parent).
>>
>>> Confused: The kids slot is a Cell, so any rule anywhere (on slots not
>>> just the ascendants) that references (kids <whatever>) will get
>>> kicked off whent that changes. More below on this.
>> I was wondering whether there would be a way to kick of that rule
>> when something deeper down in the tree gets modified (see above, the
>> family observer)
>>
>>>> If you have seen my ton of mails on the cells-gtk-devel list, you
>>>> know I'm doing some GUI work with cells-gtk at the moment. I ran
>>>> into the following issue: cells-gtk can use a family tree as a
>>>> natural representation of the contents of a tree-view. However,
>>>> when I change the items in that family tree, cells-gtk currently
>>>> has no way of updating the C data structure correspondingly.
>>>
>>>
>>> This sentence seems crucial and puzzles me some. What precisely is
>>> meant by "when I change the items in that family tree"? Do you mean
>>> reorgamize the tree by moving kids between parents?
>> Maybe this, maybe changing a cell slot on a node in the tree, maybe
>> adding kids, maybe removing them. In effect I want to keep the
>> projection of the tree onto the tree-view consistent with the tree.
>>
>>> As for "update the C data structure correspondingly", well, /what/ C
>>> data structure, this is the first I have heard of it. Do you mean the
>>> C struct implementing the tree view, or a C struct one might be
>>> "inspecting" by mapping its hierarchy to a tree of widgets?
>> The gtk tree-view displays an internal data structure, consisting of
>> rows of "cells". rows can have children. Whenever we want to put
>> some lisp structure in the treeview, we have to traverse it and build
>> the corresponding gtk stuff.
>>
>>> Let me clarify a couple of things first. btw, I do not even have
>>> Cells-Gtk installed anywhere so I may have to do that if things get
>>> too complicated.
>> I hope it won't come that far :) I really appreciate your help, esp.
>> given you won't even use cells-gtk.
>>
>>> First of all, my models normally do not have the parent slot as a
>>> Cell at all, meaning I do not move things from one parent to another.
>>> But! There have been times when I did that and it did seem to work,
>>> so let's keep that in mind going forward.
>> Probably we won't have to. I believe this one comes out of a
>> misunderstanding -- or am I not getting it?
>>
>>> Second, without looking I am almost certain the kids slot of the
>>> family class already does let applications react to changes to kids,
>>> so I am not clear on why TTO is necessary (unless we are talking
>>> about also needing the parent to be a Cell, which as I said might
>>> Just Work if we put our minds to it).
>> This confuses me. "the kids slot of the family class already does
>> let applications react to changes to kids" -- what exactly do you mean
>> by that? Adding/removing kids? Changes to the kids themselves (setf
>> (md-name (first (kids root))) "Joe")?
>> To me it looks like neither happens.
>> (defparameter root (make-instance 'node :md-name "Root" :kids (c-in
>> nil)))
>> => ROOT
>> (defparameter tview (make-instance 'tree-view :roots (c? (kids root))))
>> => TVIEW
>> (push (make-instance 'node :md-name "child") (kids root))
>> => (child)
>> ====> Nothing
>> (roots tview)
>> => ("roots have changed" (child))
>> => (child)
>> (i.e. the def-c-observer only gets called once I query the slot)
>>
>>> Third, I'd like to understand the functionality better. Is the goal
>>> to manipulate a tree on the C side via a [Cells-]Gtk tree view? Or
>>> just dynamically restucture a treeview? This is the same question as
>>> above where I ask about what is meant by "update the C data
>>> structure"?
>> The goal is
>> I modify lisp stuff
>> ==> the GTK tree model stuff ("C data structure") gets updated
>> ==> The treeview reflects my changes to the lisp stuff
>> It looks like I got myself into quite a mess here ...
>> Cheers,
>> Peter
>>
>
More information about the cells-gtk-devel
mailing list