Thread: [java-gnome-hackers] Thoughts about TreeStore
Brought to you by:
afcowie
|
From: Vreixo F. L. <met...@ya...> - 2008-03-15 18:24:17
Attachments:
treestore.patch
itervalues.diff
|
Hi!
During my work on TreeStore I've faced some problems I
want to discusse with you.
First of all, there is the model field in TreeIter. It
has a problem. Signals like TreeView.ROW_EXPANDED
return a TreeIter, which is instantiated by generic
signal handler that, obviously, do not know how to
initialize the model field. With a simple
implementation, this converts the TreeView parameter
on the signal handled in a completelly useless
parameter. The solution I've taken is add a package
protected setModel to TreeIter, together with removing
of the "final" qualifier in such field. That way, we
can implement a custom signal handler (of course,
private and hidden to the user), that initializes the
missing model field (see attached treestore.patch).
Ok, solved in a quite good way. But a bit ugly, sure.
The model field increments the implementation effort.
Not a problem, actually, if such field really provides
a better API. In my opinion, this is the case. Having
an iterNext() without the need of a model parameter is
sure a good thing. However, given we need extra effort
to have the model parameter in TreeIter, why don't we
take more advantage for each. Of course, I'm
presenting again my old proposal for having the
setValue/getValue function in TreeIter instead of of
TreeModel (see attached itervalues.diff).
This allow to set values of a row without having the
model, and it is useful, for example, to access the
values of a row in a signal handler without needing to
take a reference to the TreeModel. It is already on
TreeIter? Why force users to add extra code to get it?
------
Another question is the way CellRenderers are created.
They always take a CellLayout (ie, a TreeViewColumn)
as a parameter. I'm not against this, but what I don't
like is that they're always added to the given
CellLayout with the expand property set to true. Maybe
I'm missing something (help me!), but it seems it
can't be changed later. If so, this is a design
pitfall. Reason? Think about the left panel of an app
like nautilus (the tree of directories). It is a
TreeView with a single TreeViewColumn, with two
CellRenderers, one for the icon, one for the directory
name. If we set the expand property of the icon to
true (as it seems forced by java-gnome), when the
TreeView gets expanded it appear an ugly white space
between the icon and the dir name. This is ugly. How
can I handle this properly? Is it possible with
current design? If not, we should change this, maybe
with an alternate constructor that takes an additional
"boolean expand" parameter.
Cheers,
Vreixo
Abra sua conta no Yahoo! Mail, o único sem limite de espaço para armazenamento!
http://br.mail.yahoo.com/ |
|
From: Andrew C. <an...@op...> - 2008-03-15 19:46:21
|
I am subscribed to the java-gnome-hackers mailing list. You don't need to send messages To me and Cc list. Just send it To the list. AfC Berlin |
|
From: Andrew C. <an...@op...> - 2008-03-23 23:47:21
|
Hi Vreixo,
Sorry I didn't reply earlier. Thanks for politely nudging me to ask for
some design calls. Let's see:
On Sat, 2008-03-15 at 15:24 -0300, Vreixo Formoso Lopes wrote:
> First of all, there is the model field in TreeIter. It
> has a problem. Signals like TreeView.ROW_EXPANDED
> return a TreeIter, which is instantiated by generic
> signal handler that, obviously, do not know how to
> initialize the model field.
Right.
So we both know the usual way to engineer around this. Before we just
blindly head off down that road, it occurs to me to just copy in the
comment that's around the current TreeIter protected <init>(long)
constructor.
/*
* The protected constructor was originally removed entirely, but it turns
* out we need it for signals like ROW_ACTIVATED. This is a problem,
* because it means we'd have to jump through *many* hoops to populate the
* model field. Instead, we just cripple this TreeIter as far as iterating
* goes but that's ok because you never need to iterate from a TreeIter in
* a signal callback - it's just used to point at a row, done.
*/
protected TreeIter(long pointer) {
super(pointer);
model = null;
}
So having thought about this some more, I kinda still feel that this
argument holds. TreeIter-as-thing-that-points-at-a-row and
TreeIter-as-iterating-mechanism are really two entirely different use
cases. It's unfortunate that the same struct is used for both.
More generally, I have just been burned by iterating via TreeIter and
changing something (which I thought harmless) causing the TreeIter to
fail. (solving this is either going to mean using a TreeRowReference[]
and looping over it, or TreeModelSort. Not sure yet). Anyway, I'm even
less impressed with TreeIter than I was.
> Ok, solved in a quite good way. But a bit ugly, sure.
No, it's what's necessary - if one assumes that we can't "cripple" the
TreeIters in such cases.
So here's the question: when you get a ROW_EXPANDED event, do you need
to point at a row [ie call model.getValue() with it] or do you then need
to iterate over the model?
I've never seen the later case **from that iterator** - I _have_
subsequently called getIterFirst() and started from the top - but not
from the original TreeIter supplied by the callback.
All in all, this is a case of C-API-convenience vs
essence-of-the-toolkit. The trick is to figure out which one.
Have a think about the question I asked, and we'll chat again in a few
days.
AfC
Vancouver
|
|
From: Vreixo F. L. <met...@ya...> - 2008-03-24 00:19:00
|
> So here's the question: when you get a ROW_EXPANDED
> event, do you need
> to point at a row [ie call model.getValue() with it]
> or do you then need
> to iterate over the model?
good question! I think iteration from a arbitrary row
is not an use case. Usually you catch ROW_EXPANDED
just to get some of the row values (i.e calling
model.getValue()). But the question is: is that a
problem for us? Can we assume the user is not going to
iterate, and thus leave model to null? In my opinion
this is a bad solution, because in that case we have a
set of TreeIter methods that sometimes work, sometimes
not! It is hard for the developer to figure out in
which situations it is valid or not, even if we
carefully document that.
In my opinion, we should try to keep the same behavior
for all iterators, despite of where they come from.
Anyway, it is not hard to achieve, it is implemented
in my branch!
And note that other methods that need the model, such
as children(), are really useful in a ROW_EXPANDED
handler, so...
Cheers,
Vreixo
Abra sua conta no Yahoo! Mail, o único sem limite de espaço para armazenamento!
http://br.mail.yahoo.com/
|