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
<[EMAIL PROTECTED]> 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
_______________________________________________
cells-gtk-devel site list
[email protected]
http://common-lisp.net/mailman/listinfo/cells-gtk-devel