The Source for Java Technology Collaboration

Home » java.net Forums » Java Desktop Technologies » SwingLabs

Thread: Sneak Preview: new SwingX JXTreeTable - queen-quality

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 34 - Last Post: Jul 17, 2008 6:46 AM by: Kleopatra
Kleopatra
Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 9, 2008 5:36 AM
  Click to reply to this thread Reply


.. whatever that's worth <g>

As already announced in the other thread:



I had been playing with Netbean's new Outline related parts. It's been
veery goood start - but still required lots of work (<evil grin> Tim,
you did get the event notification only slightly more correct as we had
it - probably didn't look into the SwingX sources/issues?</evil grin> My
incubator version comes with a text file where I jotted down the
thingies I found during my experiments).


The code is in the swinglabs incubator, src folder
src/kleopatra/foreign, package netbeans.xoutline. Compiles with 1.6 (or
1.5 with target 6. target 5 doesn't work due to the changed @override
tag only - myyy dear, is that annoying!) The participants


*XOutlineModel*

that's the (mostly internal) model for the treetable. It is-a TreeModel
and is-a TableModel, has additional functionality to convert
row-coordinates to path-coordinates (and vice versa) and to control the
expansion behaviour. In contrast to the original, it exposes that
functionality in its api. Currently, it still exposes the internal
controllers (LayoutCache for the row-mapping services and
TreePathSupport for the expansion) but I hope to get that hidden soon.


*TreePathSupport* (probably to be renamed to ExpansionControl or similar)

this is the break-out of the expansion control in JTree: encapsulates
expansion memory and will/expand-notification. Part of it was already
done in the Netbeans version, so I just completed the c&p from there and
made sure that it behaves exactly the same way as JTree. Doing so, I got
rid off one of the more annoying "features" of a tree: it's tendency to
always collapse a subtree which fired a structureChange. Actually I
think that might be a bug in core: there's a check for sameness which
might be meant to be a check for equality ;-)



*DefaultXOutlineModel*

an implementation which is based on a TreeTableModel. As such it's the
congenial partner of a treeTable, swingx style: it replaces both the
tree-renderer and the TreeTableModelAdapter. In the same way those were,
it is meant as an implementation detail of the treetable. If need be, we
could open it up a bit to allow to plug-in custom implementions of
outlineModel, but wouldn't expect too many implementations - too many
nasty details to think about ;-) For the daring developer, there are
bunches of unit tests to implement against, so go ahead!



*XOutlineEventBroadcaster*

a secret servant of the DefaultX implementation which basically is
responsible to fire tree- and tableEvents on behalf of the outlineModel.
As always the path-to-row conversion is the nasty part, Netbeans
original (EventBroadcaster) got part of it right (particalurly nice: the
mapping of discontigous tree-events to multiple tableEvents). Very
ambitious but not entirely correct was the mapping of expansion change
to insert/delete tableEvents (which SwingX only mapped to dataChanged).
Couldn't resist to take up the challenge <g>


*JXXTreeTable*

it's a c&p'ed JXTreeTable with all tree-renderer references replaced by
XOutlineModel references (and all hacks removed :-). The api didn't
change much (or will not be the end), so I expect a rather smooth
replacement in client code, should be mostly transparent. While not yet
entirely complete, all (okay, can't be sure yet, so let's say most) of
out long-standing issue with selection vanished. Plus the standard
renderers/editors are used - another of our long-standing requirements.


*BasicXX, TreeTableAddon*

belongs into plaf and is meant to be as invisible as possible :-) The
UI-delegate is a subclass of BasicTableUI - and as such not very
extendable (would have to c&p the complete paintXX block just to pass-in
a renderer for the tree cell in that layer), so I opted for just
prefixing the renderer/editor-related parts witn "Basic" to hint at
their potential of being invisible to client code instead of actually
let the delegate control them. The trick right now is in the
JXXTreeTable.getCellRenderer (similar for editor): it passes the
standard renderer over to the BasicXXRenderer for wrapping and return
the BasicXX (works for SwingX style renderers aka componentProvider only)


*XXTest, XXVisualCheck, XXIssues*

those with XX=JXXTreeTable are c&p'd from the corresponding JXTreeTable
- the rename was painless and they behave well: that's one of the
reasons why I'm fairly confident that replacing our hacky treetable with
the new one will go rather smoothly. And those with XX=XOutlineModel
define its contracts rather completely (okay, not yet - exaggerating as
always <g>)


There's one rather cool design idea in Netbean's default outlineModel
with I didn't yet follow but will soon: the idea is to decorate any
plain ol' TreeModel with the tabular information (they call it
RowModel). Its methods are similar to those which characterize a
TreeTableModel (vs. a TreeModel). That's nice, because then it's
possible to combine a TreeModel implementation (which is painful most of
the time) with multiple RowModels (which is small coin). So I think it
would be worthwhile to add such a pluggable TreeTableModel implemenation
to our SwingX zoo.

Okay, that's for now - feedback highly welcome! In fact, I'm starving
for it: critics, complaints, love messages ... whatever :-)

Enjoy
Jeanette





---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 9, 2008 5:38 AM   in response to: Kleopatra
  Click to reply to this thread Reply

Kleopatra schrieb:
>
>
> As already announced in the other thread:
>
>

forgot the link:

http://forums.java.net/jive/thread.jspa?threadID=42470&tstart=50

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


i30817

Posts: 386
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 9, 2008 1:47 PM   in response to: Kleopatra
  Click to reply to this thread Reply

I really appreciate the work you do fixing core bugs and promoting correct practices. Thank you.

rturnbull

Posts: 460
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 9, 2008 10:35 PM   in response to: Kleopatra
  Click to reply to this thread Reply

I downloaded xoutline to have a look but unfortunately it wouldn't compile.
Apart from all the testing stuff, which I can ignore, BasicTreeTablePanel needs changes
made to WrappingIconPanel made on 2008-06-26.
The latest weekly build I can find is for 2008-06-22 on Swinglabs.org.
(On Hudson its 2008-05-18)
I am reluctant to start downloading individual java files, so until (or if :) ) the weekly build is
fixed I am stuck.

Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 9, 2008 11:40 PM   in response to: rturnbull
  Click to reply to this thread Reply

Ray,
> I downloaded xoutline to have a look but unfortunately it wouldn't compile.
> Apart from all the testing stuff, which I can ignore, BasicTreeTablePanel needs changes
> made to WrappingIconPanel made on 2008-06-26.
> The latest weekly build I can find is for 2008-06-22 on Swinglabs.org.
> (On Hudson its 2008-05-18)
>

arrggg ... wasn't aware that Hudson is down ... thanks for the alert!
Just for comparing notes: Hudson and swinglabs.org downloads should have
the same latest successful, which on Hudson has the build #91, done at
22. Jun. 2008 as far as I can see on

http://swinglabs.java.sun.com/hudson/job/SwingX%20Weekly%20Build/

are we talking about the same?
> I am reluctant to start downloading individual java files, so until (or if :) ) the weekly build is
> fixed I am stuck.
>

well, qualitatively, a weekly is the same as a continous - so you could
declare any of them as your special weekly <g>. But completely
understand your point - would be reluctant myself.

Thanks for trying!
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


rturnbull

Posts: 460
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 10, 2008 12:45 AM   in response to: Kleopatra
  Click to reply to this thread Reply

> Just for comparing notes: Hudson and swinglabs.org
> downloads should have
> the same latest successful, which on Hudson has the
> build #91, done at
> 22. Jun. 2008 as far as I can see on
>
> http://swinglabs.java.sun.com/hudson/job/SwingX%20Week
> ly%20Build/

I went to https://swingx.dev.java.net/ and clicked on 'automated builds'
That took me to http://swinglabs.org/hudson/ and the latest Swingx weekly build took
me to http://swinglabs.org/hudson/job/SwingX%20Weekly%20Build/

>
> are we talking about the same?

I don't know :(

Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 10, 2008 12:45 AM   in response to: rturnbull
  Click to reply to this thread Reply

jdnc-interest@javadesktop.org schrieb:
>> Just for comparing notes: Hudson and swinglabs.org
>> downloads should have
>> the same latest successful, which on Hudson has the
>> build #91, done at
>> 22. Jun. 2008 as far as I can see on
>>
>> http://swinglabs.java.sun.com/hudson/job/SwingX%20Week
>> ly%20Build/
>>
>
> I went to https://swingx.dev.java.net/ and clicked on 'automated builds'
> That took me to http://swinglabs.org/hudson/ and the latest Swingx weekly build took
> me to http://swinglabs.org/hudson/job/SwingX%20Weekly%20Build/
>
>

outch .. that link is outdated (server broken or something)- the new
server is swinglabs.java.sun.com, definitely should update that link
(where's the cleansing boy <g>)

Thanks!
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 11, 2008 8:19 AM   in response to: rturnbull
  Click to reply to this thread Reply

Ray,
> Apart from all the testing stuff, which I can ignore, BasicTreeTablePanel needs changes
> made to WrappingIconPanel made on 2008-06-26.
>

just removed that dependency (I plan to replace the WrappingIconPanel
with the BasicTreeTablePanel, names pending, as always ;-) Should
compile now ... at least I hope so.

Cheers
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


timboudreau

Posts: 4
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 10, 2008 12:19 PM   in response to: Kleopatra
  Click to reply to this thread Reply

Very happy to see this stuff migrating into JXTreeTable - this is really cool!

A couple of thoughts:
- There is a general need in Swing for something like outline's RenderDataProvider: It would be nice to see that survive and even become a general feature of Swing (in my dreams :-)) - that is, if you want to change the painting of a JTree or JList or whatever, usually you just want to replace the icon and the text. Yet the only way Swing offers to do this is to implement *CellRenderer or subclass Default*CellRenderer. Anyone who implements the interfaces (most likely over a JLabel) is likely not to know that, for example, you can double the rendering performance by no-opping out firePropertyChange(String, Object, Object) (disables Swing HTML rendering), or to override validate() and other things to be no-ops. Would make for *much* less work for the common case.

Probably there's more of a case for that to just become a feature of Default*CellRenderer in Swing in some future rev of Swing; but it certainly would make life easier for the mass of programmers who don't want to deal with the nitty gritty of component painting or cell rendering using JXXTreeTable today.

- Scott Violet had a look at the Outline code a couple of years ago, and commented that, since an OutlineModel holds layout data, it could not be reused across two components (a thing that, in practice, nobody actually needs - it's just a component hat-trick - but it does prove that the model is really separate). I think he is correct about that; if the layout stuff could be moved into a proper UI delegate, that could solve that problem and OutlineModel could be exposed. Did you do something like that? Or is XOutlineModel mostly older JXTreeTable code?

- Giving it a proper UI delegate is good; I worry a little for the necessary prettification on Mac OS (animated expansion icons and such) and other OS's. Hopefully if the tree expansion icons are right (easy to get from UIManager), the world will not at least initially notice the rest :-)

Thanks for doing this! I'm thrilled!

-Tim

Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 11, 2008 12:52 AM   in response to: timboudreau
  Click to reply to this thread Reply

Hi Tim,

> - There is a general need in Swing for something like outline's RenderDataProvider: It would be nice to see that survive and even become a general feature of Swing (in my dreams :-)) - that is, if you want to change the painting of a JTree or JList or whatever, usually you just want to replace the icon and the text. Yet the only way Swing offers to do this is to implement *CellRenderer or subclass Default*CellRenderer. Anyone who implements the interfaces (most likely over a JLabel) is likely not to know that, for example, you can double the rendering performance by no-opping out firePropertyChange(String, Object, Object) (disables Swing HTML rendering), or to override validate() and other things to be no-ops. Would make for *much* less work for the common case.
>
>

yeah, agreed - but solved in SwingX and documented in its wiki <g>. In a
short summary: the pluggable parts to change the display of cell content
are called StringValue, IconValue ...(naming does not belong to my
strengths ..;) The collaborator to plug them into is a
ComponentProvider which takes care of all the dirty details of default
config. This is done once per type of rendering component and later
re-used as-is, for all types of collection components (our
DefaultXXRenderers are mostly glue to legacy code). Special visuals
effects (like differing color, border, font ..) are considered to be
out-of-scope of renderers and applied later in the tree, table, list in
prepareRenderer via Highlighters. So life _is_ easy for SwingX
developers :-)
> - Scott Violet had a look at the Outline code a couple of years ago, and commented that, since an OutlineModel holds layout data, it could not be reused across two components (a thing that, in practice, nobody actually needs - it's just a component hat-trick - but it does prove that the model is really separate). I think he is correct about that; if the layout stuff could be moved into a proper UI delegate, that could solve that problem and OutlineModel could be exposed. Did you do something like that? Or is XOutlineModel mostly older JXTreeTable code?
>

Nitpicking a bit: principally not entirely true - the components would
have the same layout state, similar to two tables sharing the same
ColumnModel ... not that I would want to do it. Being a separation freak
makes mixing layout and data just a horrible thing to do. So in my
perspective the outlineModel is a slave class doing the hard stuff in
the background (the ui might be a good place for it, we'll see), client
code would not communicate with it. The "model" of a JXTreeTable is a
TreeTableModel (misnomer - this time not mine har, har) which is a
TreeModel with additional per-node columnnar info, the latter being very
similar to Outline's RowModel. This TreeTableModel is what client code
talks with. So I have no intention to expose the outlineModel. And no,
it doesn't contain older treetable code - fortunately, most of that
could be thrown away :-). It's mostly delegate methods to its contained
TreeTableModel and its controllers (which I want to hide as much as
possible, ghastly things are sure to happen if the layout and the
pathSupport get out off synch)
> - Giving it a proper UI delegate is good; I worry a little for the necessary prettification on Mac OS (animated expansion icons and such) and other OS's. Hopefully if the tree expansion icons are right (easy to get from UIManager), the world will not at least initially notice the rest :-)
>
>
We here at SwingX are accustomed to get bashings for the unpolished
state of new components (the statusbar f.i. hurts the eye in Vista) <g>
> Thanks for doing this! I'm thrilled!
>
>

Me too! Wouldn't have done anything without your great break-through, so
a crate of thanks back :-)

CU
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


timboudreau

Posts: 4
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 11, 2008 10:16 AM   in response to: Kleopatra
  Click to reply to this thread Reply

BTW, you mentioned renaming TreePathSupport - I agree - it grew to be more than its name portends. How about ExpansionModel? That seems to sum up what it is nicely.

-Tim

timboudreau

Posts: 4
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 11, 2008 10:32 AM   in response to: Kleopatra
  Click to reply to this thread Reply

BTW, what of isHtmlDisplayName()? I'm guessing that will go away... In all NetBeans trees/tables/lists (the Nodes API provides a common model and you just use a list/tree/table as you need against it, so the code is all in one place), we bypass Swing HTML rendering (don't want to make and throw away a DOM tree for every node during painting for performance reasons) by no-opping firePropertyChange() in our renderers. Then we use a high-performance (10x faster painting performance than Swing HTML rendering time on an old Ultra 60 when I measured it in '04) HTML renderer that only supports a limited subset of HTML (, , , and various more common SGML entities such as ™, " and a handful of others) and as a further optimization, allow the model to actually specify during rendering whether or not HTML is present. Also supports non-standard color specification to pull from UIManager color values, which is pretty handy for working with themed UIs to ensure contrasting colors. The high-speed HTML renderer might be a nice long-term optimization for Swing renderers (probably would have to be turned on explicitly for backward compatibility) - most people aren't embedding images or applets in their cell renderers anyway :-) Anyway, finding a way to keep that there (or allow the renderer to cast and find it) would make it easier for NetBeans to eventually drop its version of the code and pick up the SwingX version. Another tweak I'd love to see in JTree/List/Table that goes hand-in-hand with the above is private boolean firstPaint; public void updateUI() { super.updateUI(); firstPaint = true; } public void paint (Graphics g) { if (firstPaint) { computeFontSize(g); //will trigger a repaint return; } super.paint(g); } private void computeFontSize (Graphics g) { FontMetrics fm = g.getFontMetrics (getFont()); setFixedCellHeight (Math.max (16, fm.getHeight() + 2); //or equivalent method depending on component, 16 as default icon size but could be fetched from somewhere } Thus, after the first paint, all the rows do not need to be iterated to compute preferred size (could also compute it after addNotify() with that hellacious chain of method calls ending in a Graphics from a 1x1 BufferedImage compatible with the graphics device, but, ugh...). But I digress... -Tim

Tim Boudreau
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 11, 2008 10:37 AM   in response to: timboudreau
  Click to reply to this thread Reply

[nobr]
On Jul 11, 2008, at 1:32 PM, jdnc-interest@javadesktop.org wrote:

> BTW, what of isHtmlDisplayName()? I'm guessing that will go away...
>
> In all NetBeans trees/tables/lists (the Nodes API provides a common
> model and you just use a list/tree/table as you need against it, so
> the code is all in one place), we bypass Swing HTML rendering (don't
> want to make and throw away a DOM tree for every node during
> painting for performance reasons) by no-opping firePropertyChange()
> in our renderers. Then we use a high-performance (10x faster
> painting performance than Swing HTML rendering time on an old Ultra
> 60 when I measured it in '04) HTML renderer that only supports a
> limited subset of HTML (, , , and various more common
> SGML entities such as ™, " and a handful of others) and
> as a further optimization, allow the model to actually specify
> during rendering whether or not HTML is present. Also supports non-
> standard color specification to pull
> from UIManager color values, which is pretty handy for working with
> themed UIs to ensure contrasting colors.
>
> The high-speed HTML renderer might be a nice long-term optimization
> for Swing renderers (probably would have to be turned on explicitly
> for backward compatibility) - most people aren't embedding images or
> applets in their cell renderers anyway :-) Anyway, finding a way to
> keep that there (or allow the renderer to cast and find it) would
> make it easier for NetBeans to eventually drop its version of the
> code and pick up the SwingX version.
>
> Another tweak I'd love to see in JTree/List/Table that goes hand-in-
> hand with the above is
>
> private boolean firstPaint;
>
> public void updateUI() {
> super.updateUI();
> firstPaint = true;
> }
>
> public void paint (Graphics g) {
> if (firstPaint) {
> computeFontSize(g); //will trigger a repaint
> return;
> }
> super.paint(g);
> }
>
> private void computeFontSize (Graphics g) {
> FontMetrics fm = g.getFontMetrics (getFont());
> setFixedCellHeight (Math.max (16, fm.getHeight() + 2); //or
> equivalent method depending on component, 16 as default icon size
> but could be fetched from somewhere

firstPaint = false;

Sorry, forgot that. Also, apologies for the havoc putting HTML inline
wrought on the forum page - http://forums.java.net/jive/thread.jspa?messageID=286051&#286051
- I guess the web view doesn't escape raw HTML :-/

-Tim

>
> }
>
> Thus, after the first paint, all the rows do not need to be iterated
> to compute preferred size (could also compute it after addNotify()
> with that hellacious chain of method calls ending in a Graphics from
> a 1x1 BufferedImage compatible with the graphics device, but, ugh...).
>
> But I digress...
>
> -Tim
> [Message sent by forum member 'timboudreau' (timboudreau)]
>
> http://forums.java.net/jive/thread.jspa?messageID=286051
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
[/nobr]

Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 14, 2008 4:43 AM   in response to: timboudreau
  Click to reply to this thread Reply

jdnc-interest@javadesktop.org schrieb:
> BTW, what of isHtmlDisplayName()? I'm guessing that will go away...
>
>

Hmm .. never considered html in renderers (or anywhere else, always
thought of it like a gimmick without much worth, especially since it
tended to have widely varying appearances across versions ;-) - what do
you need it for and how/when do you "build" it?


Currently SwingX would have a problem with it: StringValue is the
central party responsible creating a string representation from the
cell value. This string rep is used by:

- the rendering component (or more precisely: the componentProvider
which configures the rendering component) to set an appropriate text
property.

- by matching functionality (pattern-based search, filter highlighting ...)

That's rather straightforward as long as both are considered the same.
With html interfering, they wouldn't. If absolutely necessary, we
probably could find a way, maybe allow a StringValueExt which has the
html producing code additionally and ComponentProviders which are aware
of the fact and use that when configuring the rendering component and
the plain text when serving the matching part.

As to font height - to be honest, I don't understand why you do it that
way: JXTable checks the UIManager for a default fixed rowHeight and
falls back to its getFontMetrics() if nothing found. What's the
advantage of asking the graphics? I mean, that's only the default value
- in custom code with heavy visual decorations there is no way around
iterating through the cells and finding an appropriate height, IMO.


> But I digress...
>
>

cool - I love digressions to learn from :-)

CU
Jeanette

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


kschaefe

Posts: 1,662
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 14, 2008 6:31 AM   in response to: Kleopatra
  Click to reply to this thread Reply

> With html interfering, they wouldn't. If absolutely
> necessary, we
> probably could find a way, maybe allow a
> StringValueExt which has the
> html producing code additionally and
> ComponentProviders which are aware
> of the fact and use that when configuring the
> rendering component and
> the plain text when serving the matching part.
BTW, this reminds me, what's the state of this?

http://forums.java.net/jive/thread.jspa?messageID=268681&#268681

I just looked and it's probably not good, since I failed to file a bug. :(

Karl

david_hall

Posts: 153
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 14, 2008 7:04 AM   in response to: Kleopatra
  Click to reply to this thread Reply

It seems like breaking the responsibility that StringValue has into two parts could do the trick. The two roles that this object is serving are: 1) getting a value from the model (the adapter does the actual work, but the StringValue converts type as necessary) and 2) formatting the value obtained in order render the UI. If you break these two roles apart (but let the user continue to configure both with a single StringValue as the default case) then you can avoid adding an Ext.

Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 5:19 AM   in response to: david_hall
  Click to reply to this thread Reply

Dave,
> It seems like breaking the responsibility that StringValue has into two parts could do the trick. The two roles that this object is serving are: 1) getting a value from the model (the adapter does the actual work, but the StringValue converts type as necessary) and 2) formatting the value obtained in order render the UI. If you break these two roles apart (but let the user continue to configure both with a single StringValue as the default case) then you can avoid adding an Ext.
>

hmm ... don't quite understand what you mean (not my day today, sorry
;-) The StringValue is just a converter: throw in an arbitrary object
and it pops out a string representation of the value _as it will appear_
in the cell. It's not concerned about about getting the value (that is
not inherently, though some implementations like a ComponentProvider
might) and it's not concerned about formatting in the sense of visual
attributes (like html tags would add).

The more I think about it, the more reluctant I get to add that
repsonsibility (on the StringValue): after all, we worked hard to get
that separation line - "content" (and default visual resets) on one side
and "visual decoration" on the other side. A ComponentProvider is
responsible for the former, a Highlighter for the latter. Mix-in of
visual decoration into a provider is as strongly discouraged as the
other way round (a Highlighter fiddling with content).

The arguable thingy is whether or not the separation line is a good one.
Naturally, I think it is :-) Though at times not as clear-cut as I would
like it to be, it allows for cute re-usable building blocks. And allows
to easily achieve effects I would never have dared to try before (the
latest was a per-row image crossing cell boundaries - remember the pains
that posed to the extreme makeover a couple of years ago?) Anyway,
future will tell - the more developers try it out the sooner.

Cheers
Jeanette





---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


david_hall

Posts: 153
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 6:56 AM   in response to: Kleopatra
  Click to reply to this thread Reply

> m ... don't quite understand what you mean (not my
> day today, sorry
> ;-) The StringValue is just a converter: throw in an
> arbitrary object
> and it pops out a string representation of the value
> _as it will appear_
> in the cell. It's not concerned about about getting
> the value (that is
> not inherently, though some implementations like a
> ComponentProvider
> might) and it's not concerned about formatting in the
> sense of visual
> attributes (like html tags would add).

A StringValue is an object that takes an argument of arbitrary class and returns a String. Where we're using it, we've decided that the string we expect is the string that we'll use on the UI for presentation purposes. Now, we've found another use for the string value of a piece of the model, but the UI presentation is not appropriate in some/many cases. I guess I'm suggesting that we find a way to allow for multiple converters, separated by role (ie, UI, filtering/sorting/searching), and allow (for both ease of use and backwards compatability) that if only one is given, it is used for all roles.

> The more I think about it, the more reluctant I get
> to add that
> repsonsibility (on the StringValue): after all, we
> worked hard to get
> that separation line - "content" (and default visual
> resets) on one side
> and "visual decoration" on the other side.

Good - you threw out the idea of adding responsibility via inheritance, and I was throwing my bit in to try to talk you out of it.

> The arguable thingy is whether or not the separation
> line is a good one.
> Naturally, I think it is :-)

So do I - I think it's exactly right.

Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 7:22 AM   in response to: david_hall
  Click to reply to this thread Reply

Dave,

> A StringValue is an object that takes an argument of arbitrary class and returns a String. Where we're using it,

hey - somebody is using it, that's great :-) At times I have the uncanny
feeling that I'm workin somewhere up in the clouds or down in a dungeon,
whatever the perspective <g>

> we've decided that the string we expect is the string that we'll use on the UI for presentation purposes. Now, we've found another use for the string value of a piece of the model, but the UI presentation is not appropriate in some/many cases. I guess I'm suggesting that we find a way to allow for multiple converters, separated by role (ie, UI, filtering/sorting/searching), and allow (for both ease of use and backwards compatability) that if only one is given, it is used for all roles.
>
>

ahh .. I'm beginning to see. Hmm ... rewording for testing my assumed
understanding: you found situations where you wanted to apply some
functionality (like filter, sort, search f.i.) on a string
representation of the value which was different from the one the user
sees? That is where the WYSIWYM (WhatYouSeeIsWhatYouMatch, TM, as in the
slides Jan allowed me to slip into his Bof at j1) wouldn't be fit? Could
you elaborate a bit as to the when that would be the case?

Anyway, if so - allowing different roles looks like a good suggestion.
And maybe (didn't think it through, just musing) will solve in passing a
big obstacle ahead: in jdk 6 the responsibility of providing a string
rep is in the rowsorter's wrappingModel (where it's wrong-placed, imo,
but maybe in one of the roles you detected, "nearer" to the model).
Until now, I have no idea how to consolidate swingx and jdk6 in that
respect ...


> Good - you threw out the idea of adding responsibility via inheritance, and I was throwing my bit in to try to talk you out of it.
>
>

okay, you succeeded :-)

>> The arguable thingy is whether or not the separation
>> line is a good one.
>> Naturally, I think it is :-)
>>
>
> So do I - I think it's exactly right.
>


so we are building a crowd of at least two

Thanks
Jeanette



---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Tim Boudreau
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 10:01 AM   in response to: david_hall
  Click to reply to this thread Reply


On Jul 15, 2008, at 9:56 AM, jdnc-interest@javadesktop.org wrote:

>> m ... don't quite understand what you mean (not my
>> day today, sorry
>> ;-) The StringValue is just a converter: throw in an
>> arbitrary object
>> and it pops out a string representation of the value
>> _as it will appear_
>> in the cell. It's not concerned about about getting
>> the value (that is
>> not inherently, though some implementations like a
>> ComponentProvider
>> might) and it's not concerned about formatting in the
>> sense of visual
>> attributes (like html tags would add).
>
> A StringValue is an object that takes an argument of arbitrary class
> and returns a String. Where we're using it, we've decided that the
> string we expect is the string that we'll use on the UI for
> presentation purposes. Now, we've found another use for the string
> value of a piece of the model, but the UI presentation is not
> appropriate in some/many cases. I guess I'm suggesting that we find
> a way to allow for multiple converters, separated by role (ie, UI,
> filtering/sorting/searching), and allow (for both ease of use and
> backwards compatability) that if only one is given, it is used for
> all roles.

Some years ago we looked at replacing the Nodes API in NetBeans with a
prototype called the Looks API (basically to get rid of the one-node-
per-model-object requirement and instead have one-object-per-type,
less listeners). It was somewhat similar - a rough sketch (minus a
bunch of stuff for clipboard operations and drag and drop and listener
proxying stuff to allow listening for changes in the below) would be:

public interface Look <T> {
public String getName (T t);
public String getDisplayName (T t);
public String getDescription (T t); //tooltip
public Action[] getActions (T t);
public Icon getIcon (T t);
}

There would then be a global (declarative) registry by-type which
could lazy-load Look instances on demand; but you could also provide
an alternative registry that would provide a different Look instance
per-type if you needed it. Sounds something like the sort of thing
you're (pardon the pun) looking for...

It's not in NB's hg repository as far as I know - we ended up deciding
not to replace and deprecate one of the most heavily used APIs in
NetBeans, but you can find a historical copy here. I know at least
Nokia uses it in their RCP app: http://www.netbeans.org/source/browse/openide/looks/src/org/netbeans/?only_with_tag=release60

-Tim

>> The more I think about it, the more reluctant I get
>> to add that
>> repsonsibility (on the StringValue): after all, we
>> worked hard to get
>> that separation line - "content" (and default visual
>> resets) on one side
>> and "visual decoration" on the other side.
>
> Good - you threw out the idea of adding responsibility via
> inheritance, and I was throwing my bit in to try to talk you out of
> it.
>
>> The arguable thingy is whether or not the separation
>> line is a good one.
>> Naturally, I think it is :-)
>
> So do I - I think it's exactly right.
> [Message sent by forum member 'david_hall' (david_hall)]
>
> http://forums.java.net/jive/thread.jspa?messageID=286738
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Tim Boudreau
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 10:57 AM   in response to: Tim Boudreau
  Click to reply to this thread Reply

On Jul 15, 2008, at 1:01 PM, Tim Boudreau wrote:

> On Jul 15, 2008, at 9:56 AM, jdnc-interest@javadesktop.org wrote:
>
>>> m ... don't quite understand what you mean (not my
>>> day today, sorry
>>> ;-) The StringValue is just a converter: throw in an
>>> arbitrary object
>>> and it pops out a string representation of the value
>>> _as it will appear_
>>> in the cell. It's not concerned about about getting
>>> the value (that is
>>> not inherently, though some implementations like a
>>> ComponentProvider
>>> might) and it's not concerned about formatting in the
>>> sense of visual
>>> attributes (like html tags would add).
>>
>> A StringValue is an object that takes an argument of arbitrary
>> class and returns a String. Where we're using it, we've decided
>> that the string we expect is the string that we'll use on the UI
>> for presentation purposes. Now, we've found another use for the
>> string value of a piece of the model, but the UI presentation is
>> not appropriate in some/many cases. I guess I'm suggesting that we
>> find a way to allow for multiple converters, separated by role (ie,
>> UI, filtering/sorting/searching), and allow (for both ease of use
>> and backwards compatability) that if only one is given, it is used
>> for all roles.
>
> Some years ago we looked at replacing the Nodes API in NetBeans with
> a prototype called the Looks API (basically to get rid of the one-
> node-per-model-object requirement and instead have one-object-per-
> type, less listeners). It was somewhat similar - a rough sketch
> (minus a bunch of stuff for clipboard operations and drag and drop
> and listener proxying stuff to allow listening for changes in the
> below) would be:
>
> public interface Look <T> {
> public String getName (T t);
> public String getDisplayName (T t);
> public String getDescription (T t); //tooltip
> public Action[] getActions (T t);
> public Icon getIcon (T t);
> }

I forgot one very critical method for really building an ad-hoc tree
model from ad-hoc objects - probably beyond the scope of what you're
after though:
public List <?> getChildObjects();

...which gives you the ability to have an ad-hoc set of child objects
depending on the use case (for example, the New Project dialog in
NetBeans is a Master-Detail view that [if it were using Looks] would
have a Look that proxies the real Look for the project-types folder
tree and hides the child objects, and a detail list that shows the a
list of the actual provided children).

(there was also a way to get properties for an object - it's somewhat
useful to think of the properties of an object [which have their own
object values] as simply a secondary child-hierarchy of the model
object - once you're doing something like this, the concepts unify
nicely).

-Tim

>
>
> There would then be a global (declarative) registry by-type which
> could lazy-load Look instances on demand; but you could also
> provide an alternative registry that would provide a different Look
> instance per-type if you needed it. Sounds something like the sort
> of thing you're (pardon the pun) looking for...
>
> It's not in NB's hg repository as far as I know - we ended up
> deciding not to replace and deprecate one of the most heavily used
> APIs in NetBeans, but you can find a historical copy here. I know
> at least Nokia uses it in their RCP app: http://www.netbeans.org/source/browse/openide/looks/src/org/netbeans/?only_with_tag=release60
>
> -Tim
>
>>> The more I think about it, the more reluctant I get
>>> to add that
>>> repsonsibility (on the StringValue): after all, we
>>> worked hard to get
>>> that separation line - "content" (and default visual
>>> resets) on one side
>>> and "visual decoration" on the other side.
>>
>> Good - you threw out the idea of adding responsibility via
>> inheritance, and I was throwing my bit in to try to talk you out of
>> it.
>>
>>> The arguable thingy is whether or not the separation
>>> line is a good one.
>>> Naturally, I think it is :-)
>>
>> So do I - I think it's exactly right.
>> [Message sent by forum member 'david_hall' (david_hall)]
>>
>> http://forums.java.net/jive/thread.jspa?messageID=286738
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
>> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 16, 2008 1:32 AM   in response to: Tim Boudreau
  Click to reply to this thread Reply

Tim Boudreau schrieb:
>
> public interface Look <T> {
> public String getName (T t);
> public String getDisplayName (T t);
> public String getDescription (T t); //tooltip
> public Action[] getActions (T t);
> public Icon getIcon (T t);
> }
>
> There would then be a global (declarative) registry by-type which
> could lazy-load Look instances on demand; but you could also provide
> an alternative registry that would provide a different Look instance
> per-type if you needed it. Sounds something like the sort of thing
> you're (pardon the pun) looking for...

haha, looks familiar - a collection similar to that (without the
actions) is called "PresentationAttributes" in my SwingEmpire
Formbuilder - which rests in peace (or pieces <g>) since I'm working here.

actually ... no, don't think so: a XXValue is meant to be very, very
single-minded. One method, one conversion, one task. And when it comes
to rendering, a fixed type is a bit contra-productive - renderers must
cope with any type, so XXValues must as well ;-) Especially with that
damned type erasure ...

CU
Jeanette




---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Tim Boudreau
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 14, 2008 8:19 AM   in response to: Kleopatra
  Click to reply to this thread Reply


On Jul 14, 2008, at 7:43 AM, Kleopatra wrote:

> jdnc-interest@javadesktop.org schrieb:
>> BTW, what of isHtmlDisplayName()? I'm guessing that will go away...
>>
>>
>
> Hmm .. never considered html in renderers (or anywhere else, always
> thought of it like a gimmick without much worth, especially since it
> tended to have widely varying appearances across versions ;-)

You do have to do some magic to avoid getting that darned Serif font :-)

> - what do you need it for and how/when do you "build" it?

You've probably noticed that in NetBeans, the tree node that
represents the "main" project is boldfaced - that is using HTML.
Also, the, if you turn on View | Versioning Labels, you'll notice that
the file version, branch info, etc. appears in light grey text
appended to the file name for each file in the Projects of Files
view. All of this is using HTML. In NB the view components know
nothing about what their model data is - so there's no replacing cell
renderers. Instead there is a "presentation layer" - the Nodes API -
in between the data model and the visual representation. That
presentation layer adds human-friendly attributes such as icon,
display name, tooltip, popup-menu items, etc., to whatever data model
the module author wants to create (it also potentially rearranges the
hierarchy, like the java package view). The Explorer API provides
JTree, JList, etc. components, and you just plop whatever kind of
component you want into a container, it looks up through the hierarchy
to find a parent that implements ExplorerManager.Provider, and uses
the resulting ExplorerManager to find the root node it should show and
manage selection. A bit more about that here: http://platform.netbeans.org/tutorials/60/nbm-selection-2.html

A major benefit is you have one model, and slap whatever component you
want on top of it, be it a JTree, JList, tree table, etc., without
needing to rewrite anything.

So basically, everyone uses the same components for JLists, JTrees,
etc. throughout NetBeans. It's up to the "presentation layer" (adding
human-friendly attributes to an ad-hoc data model) to decorate Nodes
appropriately. And since they don't control the cell renderer (and in
fact have no idea what kind of component they're being displayed in),
there needs to be a way to allow for boldface, colored text, etc.
HTML solves that problem perfectly. Since there is a legitimate case
for node display names containing Currently SwingX would have a problem with it: StringValue is the
> central party responsible creating a string representation from the
> cell value. This string rep is used by:
>
> - the rendering component (or more precisely: the componentProvider
> which configures the rendering component) to set an appropriate text
> property.
>
> - by matching functionality (pattern-based search, filter
> highlighting ...)
>
> That's rather straightforward as long as both are considered the
> same. With html interfering, they wouldn't. If absolutely necessary,
> we probably could find a way, maybe allow a StringValueExt which has
> the html producing code additionally and ComponentProviders which
> are aware of the fact and use that when configuring the rendering
> component and the plain text when serving the matching part.

Could you point me to where all this IntValue, StringValue stuff is?
I'll understand it better if I play with it.

> As to font height - to be honest, I don't understand why you do it
> that way: JXTable checks the UIManager for a default fixed rowHeight
> and falls back to its getFontMetrics() if nothing found. What's the
> advantage of asking the graphics?

If I recall the reasons for it correctly, there could be issues with
multiple monitors otherwise, although the current solution only helps
if the window is never moved between monitors.

Generally, most Swing programmers are almost if not completely unaware
of UIManager - so anything requiring the application to put a special
value in UIManager is something 99% of Swing programmers (I
specifically *don't* mean people on this list) are ever going to
discover. So their trees, lists and tables will be much slower in
layout operations than they need to be. That's why I'd like to see
something like this built-in to JTree.

Until I read the above, *I* didn't know you could specify a fixed row
height in UIManager - is that just a SwingX thing?

In the case of NetBeans, it is an extensible application - so it's
entirely possible that someone will write a plugin where the default
fixed height value is wrong for that one component for some reason -
maybe they're doing multi-line tree nodes with a JTextArea as a
renderer or something. So we can't really impose a fixed height
globally.

> I mean, that's only the default value - in custom code with heavy
> visual decorations there is no way around iterating through the
> cells and finding an appropriate height, IMO.

For cases where the height or icon size really will vary, there isn't
one. In my experience, most people just want to fiddle with the icon
and display text, and aren't doing varying height icons or multi-line
text. We've had fixed-height with the ability to use HTML for text
decoration in trees and tables in NetBeans since 2004, and people use
them quite a bit, but I've never seen a request to allow varying
height cells or anything like that, nor a bug report about fixed height.

-Tim

>
>
>
>> But I digress...
>>
>>
>
> cool - I love digressions to learn from :-)
>
> CU
> Jeanette
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 5:38 AM   in response to: Tim Boudreau
  Click to reply to this thread Reply

Tim Boudreau schrieb:
>> - what do you need it for and how/when do you "build" it?
>
> You've probably noticed that in NetBeans, the tree node that
> represents the "main" project is boldfaced - that is using HTML.
> Also, the, if you turn on View | Versioning Labels, you'll notice that
> the file version, branch info, etc. appears in light grey text
> appended to the file name for each file in the Projects of Files view.

okay, I see. In SwingX, tweaking visuals on a per-cell bases is the task
of Highlighters. They can be defined anywhere, attached to anything and
work in all types of "collection components". Their smallest unit of
interest (as everything's else) is the cell, sub-cell (as f.i. two fonts
in one label) granularity is not covered . Hmmm ... need to think a bit.

>
> Could you point me to where all this IntValue, StringValue stuff is?
> I'll understand it better if I play with it.

it's part of SwingX, renderer package. Documentation is a sore point ;-)
Code examples are in the demo hierarchy, the test hierarchy (classes
with "VisualCheck" postfix), and the swinglabs-demos project. And we
have the wiki with random notes and some relevant links.

>
> If I recall the reasons for it correctly, there could be issues with
> multiple monitors otherwise, although the current solution only helps
> if the window is never moved between monitors.
>

ahh .. thanks, wasn't aware of it.

>
> Until I read the above, *I* didn't know you could specify a fixed row
> height in UIManager - is that just a SwingX thing?
>

yeah ... and probably undocumented except in code ;-) ehem ....


Thanks for your input - much food for my brain :-)

Jeanette


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 4:21 AM   in response to: Kleopatra
  Click to reply to this thread Reply

Kleopatra schrieb:
>
> There's one rather cool design idea in Netbean's default outlineModel
> with I didn't yet follow but will soon: the idea is to decorate any
> plain ol' TreeModel with the tabular information (they call it
> RowModel). Its methods are similar to those which characterize a
> TreeTableModel (vs. a TreeModel). That's nice, because then it's
> possible to combine a TreeModel implementation (which is painful most
> of the time) with multiple RowModels (which is small coin). So I think
> it would be worthwhile to add such a pluggable TreeTableModel
> implemenation to our SwingX zoo.
>
>

tried it (it's in my incubator, in the rendererdemo under the xoutline
package) - something along the lines of:

class TabularTreeModel implements TreeTableModel {
   // the wrapped treemodel
    private TreeModel treeModel;
   // the additional columnar info (aka RowModel in Netbeans, with 
SwingX method signatures)
   NodeModel nodeModel;
    // the TreeModelSupport firing for us
   TreeModelSupport modelSupport;
 
   public TabularTreeModel(TreeModel delegate, NodeModel nodeModel) {
       modelSupport = new TreeModelSupport(this);
        this.treeModel = delegate;
        // install a listener to refire events from the delegate
       delegate.addTreeModelListener(new DelegateListener());
  }
  
  private class DelegateListener implements TreeModelListener {
         public void treeNodesChanged(TreeModelEvent event) {
                modelSupport.fireChildrenChanged(event.getTreePath(), ...);
        }
         .....
  }
//---------- implement TreeModel, just delegate
 
    public Object getRoot() {
         return treeModel != null ? treeModel.getRoot() : null;
    }
 
// ----------- implement TreeTableModel, delegate to nodeModel
  
   public void getValueAt(Object node, int column) {
         return nodeModel.getValueAt(node, column);
   }
 
   .........
 
 
// and here comes the show-stopper
 
    public void setValueAt(Object value, Object node, int column) {
           if (!isCellEditable(node, column) return;
           nodeModel.setValueAt(value, node, column);
          // how to fire a correct TreeModelEvent?
    }
 
}


(as an aside, the EventBroadcaster in Netbeans outline has the same
problem - and decided to ignore it ;-)

Thinking a bit, my conclusion is that the core TreeModel api just isn't
rich enough.

- implementations are required to fire TreeModelEvents on change
- the "coordinate" of a TreeModelEvent is a TreePath

The implication is that each and every treeModel (except those which are
neither modifiable nor mutable) implementation *must* have a means to
create a path to its root to comply with its notification contract. So:
shouldn't that be reflected in the api? If so, how about adding a new
model type to the SwingX zoo, something like:

interface TreeModelExt extends TreeModel {
     /**
      *  Returns a TreePath identifying the given node.
      * @param node a node managed by this model, must not be null
      * @return a treepath identifying the node
      * @throws IllegalArgumentException if the node is not managed
      * @throws NPE if the node is null
      */
     TreePath getTreePath(Object node);
}


With that in place, the model above could fire the required
treeModelEvent on setting a column value. Or the other way round: if a
TreeModel doesn't implement the extension, it'll report the columns as
not editable.

Thoughts?

Jeanette



---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


kschaefe

Posts: 1,662
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 5:46 AM   in response to: Kleopatra
  Click to reply to this thread Reply

> The implication is that each and every treeModel
> (except those which are
> neither modifiable nor mutable) implementation *must*
> have a means to
> create a path to its root to comply with its
> notification contract. So:
> shouldn't that be reflected in the api? If so, how
> about adding a new
> model type to the SwingX zoo, something like:
> TreeModelExt

> With that in place, the model above could fire the
> required
> treeModelEvent on setting a column value. Or the
> other way round: if a
> TreeModel doesn't implement the extension, it'll
> report the columns as
> not editable.
>
> Thoughts?
I like the idea. Too bad DefaultTreeModel is tightly bound to TreeNodes. DefaultTreeModel.getPathToRoot would have been a nice way to create the interface from current APIs.

But...now we really need to add an AbstractTreeModel as well. We've toyed with the idea previously, but with the addition of a new subinterface, we should provide the additional support of an abstract base class.

Karl

Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 7:45 AM   in response to: kschaefe
  Click to reply to this thread Reply

Karl,

> I like the idea. Too bad DefaultTreeModel is tightly bound to TreeNodes. DefaultTreeModel.getPathToRoot would have been a nice way to create the interface from current APIs.
>
>

good :-) Yeah, exactly.

> But...now we really need to add an AbstractTreeModel as well. We've toyed with the idea previously, but with the addition of a new subinterface, we should provide the additional support of an abstract base class.
>
>


hmm ... don't quite see how the new interface would strengthen the
arguments in favour of an AbstractTreeModel - we couldn't provide an
implemenation of a getTreePath for the general case, or could we? We
just know that all modifiable or mutable models must have some means to
get at it, it's exact nature highly context dependent. BTW, do we have
any feedback on how often devs go from the AbstractTreeTableModel
instead of from scratch? If that's considered useful, its sibling might
as well be so.

Cheers
Jeanette





---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


kschaefe

Posts: 1,662
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 8:08 AM   in response to: Kleopatra
  Click to reply to this thread Reply

> BTW, do we have
> any feedback on how often devs go from the
> AbstractTreeTableModel
> instead of from scratch? If that's considered useful,
> its sibling might
> as well be so.
I only ever use the AbstractTreeTableModel. Oh wait, you probably wanted someone else's feedback. ;)

Karl

Tim Boudreau
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 15, 2008 9:29 AM   in response to: Kleopatra
  Click to reply to this thread Reply

On Jul 15, 2008, at 7:21 AM, Kleopatra wrote:

> // and here comes the show-stopper
>
> public void setValueAt(Object value, Object node, int column) {
> if (!isCellEditable(node, column) return;
> nodeModel.setValueAt(value, node, column);
> // how to fire a correct TreeModelEvent?
> }
>
> }
> [/code]
>
> (as an aside, the EventBroadcaster in Netbeans outline has the same
> problem - and decided to ignore it ;-)
>
> Thinking a bit, my conclusion is that the core TreeModel api just
> isn't rich enough.
>
> - implementations are required to fire TreeModelEvents on change
> - the "coordinate" of a TreeModelEvent is a TreePath
>
> The implication is that each and every treeModel (except those which
> are neither modifiable nor mutable) implementation *must* have a
> means to create a path to its root to comply with its notification
> contract. So: shouldn't that be reflected in the api? If so, how
> about adding a new model type to the SwingX zoo, something like:
>
>
>
> interface TreeModelExt extends TreeModel {
>    /**
>     *  Returns a TreePath identifying the given node.
>     * @param node a node managed by this model, must not be null
>     * @return a treepath identifying the node
>     * @throws IllegalArgumentException if the node is not managed
>     * @throws NPE if the node is null
>     */
>    TreePath getTreePath(Object node);
> }
> 

>
> With that in place, the model above could fire the required
> treeModelEvent on setting a column value. Or the other way round: if
> a TreeModel doesn't implement the extension, it'll report the
> columns as not editable.
>
> Thoughts?

The above will work. However...

I *can* think of a hacky way to do it, since the merged model is
package-private. Make the following assumptions:
- If the model is in use in a component, it will have listeners
- At least one of the listeners will belong to the Outline
component, either directly or via a UI delegate or similar - anyway,
there's a path to an Outline from a model via its listeners (there has
to be in one way or another)
- If there are no listeners belonging to the Outline, it isn't
actually useful to try to fire an event anyway

And do this:
- Create a package private interface
interface TreePathProvider {
public TreePath pathFor (int row); //don't care about column,
this only matters for the 0th/hierarchical column
}

- implement it on an inner listener class internal to Outline (or
wherever) that will be attached to the model as long as it's driving
the Outline
- To create the event, iterate the listeners on the model and try to
find one implementing that interface. Use it to get the correct tree
path, and fire the event with that.

The only case where that falls down is if someone is creating a model,
able to get hold of the TableModel (if XOutlineModel is hidden, that
should eliminate the possibility), and is using it for something other
than in an XOutline component. Should be easy enough to prohibit that
(with the possible exception of fetching the model from the component).

So, though it's not the kind of thing I find pretty, it saves
introducing a new interface to the API (always a good thing to keep
any APIs conceptual surface area as low as possible). The model is,
by nature, going to have a reference to at least one component showing
it through its listeners (it's going to anyway) if it is in use - it's
impossible for it not to. And the component knows enough about the
tree to construct a path, given a row.

If this seems too hacky, consider doing *both* and document that if
the tree model doesn't implement the optional TreeModelExt interface,
the resulting model will not fire events if the hierarchical column's
setValueAt() is called programmatically when it's not driving any
component. That way users of the API don't have to implement
getTreePath() and it will make life much easier for all users who are
not in the extreme corner case of:
- Got an old model from a component (assuming it's not exposed
directly so you'd actually have to create a model, set it on a
component, retrieve it via getModel())
- Set a new model on the component (i.e. the old model now has no
component listening on it, but the application author for some reason
does still listen on it)
- The application calls setValueAt() for a cell in the hierarchical
column in a model which is no longer in use but which they expect
their own listeners on the model to respond to

This seems like a case that is so far out there it hardly seems worth
supporting. And if you can really hide the TableModel instance so
client code can't get hold of it and call setValueAt() on it
programmatically, then it will work 100%.

-Tim


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 16, 2008 2:13 AM   in response to: Tim Boudreau
  Click to reply to this thread Reply

Tim Boudreau schrieb:
>
> The above will work. However...
>
> I *can* think of a hacky way to do it, since the merged model is
> package-private.

hmm ... not sure we are talking about the same "model"? What I have
meant was an implementation of a SwingX TreeTableModel wrapped around a
(TreeModel +NodeModel) for public usage, not package private. And at
that level no outline in sight.

For the sake of the argument (maybe it doesn't show, but I love to argue
<g>) let's assume we an outlineModel wrapped around, then

> Make the following assumptions:
> - If the model is in use in a component, it will have listeners
> - At least one of the listeners will belong to the Outline component,
> either directly or via a UI delegate or similar - anyway, there's a
> path to an Outline from a model via its listeners (there has to be in
> one way or another)
> - If there are no listeners belonging to the Outline, it isn't
> actually useful to try to fire an event anyway

> And do this:
> - Create a package private interface
> interface TreePathProvider {
> public TreePath pathFor (int row); //don't care about column, this
> only matters for the 0th/hierarchical column
> }
>
> - implement it on an inner listener class internal to Outline (or
> wherever) that will be attached to the model as long as it's driving
> the Outline
> - To create the event, iterate the listeners on the model and try to
> find one implementing that interface. Use it to get the correct tree
> path, and fire the event with that.
>

how diiirty, iiieeee ... You might get away with something like that in
Netbeans, not in SwingX - SCNR <g> A couple of comments:

- a model's contract is to be served independent of the type its
listeners and independent of whether or not it's currently used in a
view (there might be other interested parties)
- as a TreeModel it must fire a nodeChange whenever any property of the
node is changed, doesn't matter if it's one of those in tabular or in
the hierarchical column
- a TreeModel must fire nodeChange for invisible nodes (trivially, as it
doesn't know about its visibility ;-), in which case the pathForRow
wouldn't return anything useful
- a TreeModel provides no way to iterate its listeners


>
> So, though it's not the kind of thing I find pretty, it saves
> introducing a new interface to the API (always a good thing to keep
> any APIs conceptual surface area as low as possible).

my emphasis is on "as possible" ;-) Violating the notification contract
is impossible, at least on framework level (maybe I'll switch back to
application dev just to enjoy the pure fun of pragmatics). So I see no
way around the additional conceptual weight if the columns should be
editable or the other way round: they must be not-editable if there is
no way to fire the appropriate nodeChanged.

> That way users of the API don't have to implement getTreePath()

well, I think that's not a big deal as they (assuming their models are
well-behaved)

- either: have a mutable/modifiable treeModel implementation: then they
must have some means to build that path because they must fire the usual
treeEvents
- or: have a read-only model - then making the column props editable
would violate the immutability anyway

so in the first case it's simple for them to expose their intenal
mechanism, and in the second they wouldn't do anything - and be
protected from accidental edits by the outline/treetableModel default
implementation.

Cheers
Jeanette




---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Tim Boudreau
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 16, 2008 7:11 AM   in response to: Kleopatra
  Click to reply to this thread Reply

On Jul 16, 2008, at 5:13 AM, Kleopatra wrote:
> Tim Boudreau schrieb:
>>
>> The above will work. However...
>>
>> I *can* think of a hacky way to do it, since the merged model is
>> package-private.
>
> hmm ... not sure we are talking about the same "model"? What I have
> meant was an implementation of a SwingX TreeTableModel wrapped
> around a (TreeModel +NodeModel) for public usage, not package
> private. And at that level no outline in sight.

Okay. I was talking about OutlineModel (TreeModel + TableModel); if
that still exists and a TreeTableModel is delegating to it, then we're
still talking about the same thing modulo one layer of indirection :-)

> For the sake of the argument (maybe it doesn't show, but I love to
> argue <g>) let's assume we an outlineModel wrapped around, then
>
>> Make the following assumptions:
>> - If the model is in use in a component, it will have listeners
>> - At least one of the listeners will belong to the Outline
>> component, either directly or via a UI delegate or similar -
>> anyway, there's a path to an Outline from a model via its listeners
>> (there has to be in one way or another)
>> - If there are no listeners belonging to the Outline, it isn't
>> actually useful to try to fire an event anyway
>
>> And do this:
>> - Create a package private interface
>> interface TreePathProvider {
>> public TreePath pathFor (int row); //don't care about column,
>> this only matters for the 0th/hierarchical column
>> }
>>
>> - implement it on an inner listener class internal to Outline (or
>> wherever) that will be attached to the model as long as it's
>> driving the Outline
>> - To create the event, iterate the listeners on the model and try
>> to find one implementing that interface. Use it to get the correct
>> tree path, and fire the event with that.
>>
>
> how diiirty, iiieeee ... You might get away with something like that
> in Netbeans, not in SwingX - SCNR <g> A couple of comments:

I wouldn't like doing it in NetBeans either. But I like even less
forcing the user of an API to solve a problem we could have solved for
them.

> - a model's contract is to be served independent of the type its
> listeners and independent of whether or not it's currently used in a
> view (there might be other interested parties)

Understood, although *if* the case is that the model in question is a
package private type (OutlineModel, proxied by a TreeTableModel
implementation), client code can't touch it anyway. But if it's
driving a JXTreeTableModel or whatever it's called, it would not
propagate change events there, in which case the TreeTableModel would
be broken when not attached, which I think is what you're saying.

Nonetheless, it's worth asking the question whether, for *specific
instances* of the model type created through a factory method, there
is more utility to documenting a limitation of those instances (not
firing events when not attached), or requiring every user to write a
very similar chunk of code to look up tree paths. Most Swing apps in
the wild just use DefaultTreeModel for everything (not that that's
actually a good idea), and most (again, I *don't* mean people on this
list) Swing developers have never written a TreeModel from scratch.
Asking a Swing novice to write tree path lookup code so may be pretty
intimidating and difficult. I've got a couple of suggestions at the
bottom for how to keep some ease-of-use for those folks.

> - as a TreeModel it must fire a nodeChange whenever any property of
> the node is changed, doesn't matter if it's one of those in tabular
> or in the hierarchical column

I was assuming that the issue was simply around firing tree model
events for the hierarchical column, not all columns - i.e. if you
don't implement ExtTreePathProvider, you get a non-editable
hierarchical column, not all columns non-editable.

I won't argue further for the listener hack except to say the following:

We're talking about a static method (or tree table constructor
arguments?) that pumps out a specific instance (not the canonical
definition) of a model. As a library *user*, I'd rather see in the
documentation "Instances of FooModel created by this method will not
fire events when the model is not attached to an Outline component
unless the passed TreeModel implements TreeModelExt" and have less
work to do. If I'm doing something really bizarre with the model,
then I can always either implement TreeModelExt (or TreePathProvider -
see below) or implement the actual model interface myself - but for
the common case I can take my existing TreeModel and use it in a
TreeTable without adding any code.

It would be best to avoid forcing users of it to write boilerplate
wherever possible. I agree that on the fundamental level, the
contract of a model is to work a certain way. It is not unheard of to
document that "Instances created through this method have this
limitation. If you don't want that, do A., B. or C." (XML parsers,
etc). To my mind, a primary responsibility of a library author is to
not force work on common-case users of that library that the library
could do - in other words, the utility of millions of people not
having to write a pathFor() method far outweighs my desire for
architectural purity, especially if I can offer an architecturally
pure alternative for those that need it.

> - a TreeModel must fire nodeChange for invisible nodes (trivially,
> as it doesn't know about its visibility ;-), in which case the
> pathForRow wouldn't return anything useful
> - a TreeModel provides no way to iterate its listeners

Okay, here I was assuming an OutlineModel or whatever we're calling
it, which implements TreeModel + TableModel, and which has a list of
its listeners, and that this code would be internal to it. With the
added indirection of trying to find the Outline/JXTreeTable via the
TreeTableModel that is delegating to it, it gets more complicated, but
there still is a path from here to there.

>> So, though it's not the kind of thing I find pretty, it saves
>> introducing a new interface to the API (always a good thing to keep
>> any APIs conceptual surface area as low as possible).
>
> my emphasis is on "as possible" ;-) Violating the notification
> contract is impossible, at least on framework level (maybe I'll
> switch back to application dev just to enjoy the pure fun of
> pragmatics). So I see no way around the additional conceptual
> weight if the columns should be editable or the other way round:
> they must be not-editable if there is no way to fire the appropriate
> nodeChanged.
>
>> That way users of the API don't have to implement getTreePath()
>
> well, I think that's not a big deal as they (assuming their models
> are well-behaved)
> - either: have a mutable/modifiable treeModel implementation: then
> they must have some means to build that path because they must fire
> the usual treeEvents
> - or: have a read-only model - then making the column props editable
> would violate the immutability anyway
>
> so in the first case it's simple for them to expose their intenal
> mechanism, and in the second they wouldn't do anything - and be
> protected from accidental edits by the outline/treetableModel
> default implementation.

If you're going with the TreeModelExt approach, I suggest (at least
some of) the following:

- Don't actually have it extend TreeModel. Call it something like
TreePathProvider, and allow it to be implemented separately, so
someone can call
static FooModel createModel (TreeModel tree, RowModel columns,
TreePathProvider provider)
so that they can drop in an existing TreeModel unmodified (probably
also check if the TreeModel implements TreePathProvider).

- Have another static method that takes DefaultTreeModel and a
RowModel and doesn't require a TreePathProvider, since
DefaultTreeModel has enough info to do the job and we can generate a
delegate TreePathProvider to glue it together
static FooModel createModel (DefaultTreeModel tree, RowModel
columns)

- Have an abstract class that takes a TreeModel in its constructor,
implements TreeModel and TreePathProvider, does all of the delegation
to the original TreeModel and you implement pathFor(Object node).

That way someone with an existing TreeModel (that maybe they can't
change - there are libraries that will let you make a TreeModel over a
Map or Collection and you don't have access to the TreeModel
implementation) doesn't have to write all of the delegation
boilerplate to wrap a TreeModel in an TreeModelExt, and someone using
DefaultTreeModel doesn't have to do any extra work.

My concern is that I hate seeing an API where every user of it has to
write a similar blob of boilerplate that the library author could have
taken care of. Wherever we can legitimately reduce that, it's our
responsibility to.

-Tim


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 16, 2008 8:08 AM   in response to: Tim Boudreau
  Click to reply to this thread Reply

Hi Tim,

I'll read and try to digest your input carefully, and then come back to
you. For now just two quick points where we seem to talk past each other
or I'm missing something or misunderstand what you are saying:

1) Given an OutlineModel (or whatever we call it, something being a tree
and having per-node tabular data), I think it doesn't make a difference
if a node itself or any of its tabular data is edited: the api doc of
treeNodesChanged clearly:

"Invoked after a node (or a set of siblings) has changed in some way.
The node(s) have not changed locations in the tree or altered their
children arrays, but other attributes have changed and *may affect
presentation*"

I think there is no lee-way to not fire: the wrapping model is-a
TreeModel and as such must comply to that responsibility. One of The
Rules (http://wiki.java.net/bin/view/Javadesktop/SwingLabsImperialRules)
I'm constantly preaching is to not break super's contract, and
definitely don't want to be caught doing so myself :-)

2) I might be blind, but I don't see a way to implement a
TreePathProvider (which must have a method getPathForNode(Object), not
(row), IMO) in the general case from the outside - except if I knew that
the concrete model has some way to navigate to its parent or walk the
tree until I find the node in question. Which ... wouldn't be nice.

Thanks!
Jeanette



---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Tim Boudreau
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 16, 2008 9:09 AM   in response to: Kleopatra
  Click to reply to this thread Reply


On Jul 16, 2008, at 11:08 AM, Kleopatra wrote:

> Hi Tim,
>
> I'll read and try to digest your input carefully, and then come back
> to you. For now just two quick points where we seem to talk past
> each other or I'm missing something or misunderstand what you are
> saying:
>
> 1) Given an OutlineModel (or whatever we call it, something being a
> tree and having per-node tabular data), I think it doesn't make a
> difference if a node itself or any of its tabular data is edited:
> the api doc of treeNodesChanged clearly:
>
> "Invoked after a node (or a set of siblings) has changed in some
> way. The node(s) have not changed locations in the tree or altered
> their children arrays, but other attributes have changed and *may
> affect presentation*"
>
> I think there is no lee-way to not fire: the wrapping model is-a
> TreeModel and as such must comply to that responsibility. One of The
> Rules (http://wiki.java.net/bin/view/Javadesktop/SwingLabsImperialRules
> ) I'm constantly preaching is to not break super's contract, and
> definitely don't want to be caught doing so myself :-)

That depends if you consider a change columnar for a row to be a
change in the tree node for that row. I would argue that unless the
change occurred in the tree column, the node has not changed, some
other cell has. If the change in a non-tree-column cell *triggers* a
change in the object represented by the tree node, then a properly
written TreeModel will fire a node change as a side effect of the
value change.

To make this less hypothetical, say I have a little Swing CRUD
application using a tree table instead of a table. Column 0 is my
tree column. My application should change the tree icon of modified
rows to indicate that a save is needed. I make an edit in column 3.
Does an edit to column 3 constitute a change in column 0? If the
TreeModel driving column 0 is properly written, *it* should notice the
change in the object the node represents and trigger a change event
and a repaint; I don't believe it is our job to assume a change in
column 3 constitutes a change in column 0. In this example it does
(but it's the job of the TreeModel, not us, to notice the change);
for most uses of a tree table (consider a debugger, for example), the
visible content of the hierarchical column (say, names of variables
being that have watches) does not change because of a value change in
one of the other columns. In which case firing a TreeModelEvent just
triggers an unnecessary repaint and possibly other unnecessary work by
other listeners.

So, I'm not saying, don't fire tree model changes if the hierarchical
column is edited; I'm saying, don't fire tree model changes if one of
the non-hierarchical columns changes. Re fetching a tree path, for
the hierarchical column, it should be read-only unless there is a way
to get a TreePath for the node that would be changed; that does not
necessarily apply to the other columns. However, if your existing
TreeTableModel assumes being able to get a TreePath when there is a
change in any column, then that point is somewhat moot.

If an edit is made in the hierachical column, then absolutely,
treeNodesChanged() should be called. Not doing so would indeed break
the contract of TreeModel.

If a tree node was *not* the thing that was changed, then, well, the
tree node didn't change. Ergo the TreeModel didn't change. In which
case there is no reason for a TreeModelEvent to be fired. If the tree
node changes as a side-effect of a change in a non-tree column, it's
the job of the TreeModel to notice that and fire events appropriately,
not us.

> 2) I might be blind, but I don't see a way to implement a
> TreePathProvider (which must have a method getPathForNode(Object),
> not (row), IMO)

Agreed.

> in the general case from the outside - except if I knew that the
> concrete model has some way to navigate to its parent or walk the
> tree until I find the node in question. Which ... wouldn't be nice.

I'd expect that most people writing code from scratch *will* extend
their TreeModel to implement TreePathProvider, creating the equivalent
of TreeModelExt; but there is the case where someone is using a
TreeModel supplied by a library (IIRC GlazedLists is like this), where
extending the TreeModel is not possible, and they either need to wrap
it or implement path lookup separately (in which case they do need to
know how to find the path, but it's up to the library in question to
provide a means to do so - nothing can be done about it on our side).

Keeping TreePathProvider independent of TreeModel doesn't sacrifice
any value, and saves work for those who are being handed a TreeModel
they didn't create and want to use it in a tree table. Making
TreePathProvider (nee TreeModelExt) extend TreeModel doesn't add any
particular value other than making it obviously something that works
closely with a TreeModel (documentation and method signatures can
solve that); doing so does, however, make life more difficult for
people who didn't write the TreeModel they're using. So it seems to
me the minuses outweigh the pluses for having an extension interface
to TreeModel.

-Tim


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Tim Boudreau
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 16, 2008 9:25 AM   in response to: Tim Boudreau
  Click to reply to this thread Reply


On Jul 16, 2008, at 12:09 PM, Tim Boudreau wrote:

>
> On Jul 16, 2008, at 11:08 AM, Kleopatra wrote:
>
>> Hi Tim,
>>
>> I'll read and try to digest your input carefully, and then come
>> back to you. For now just two quick points where we seem to talk
>> past each other or I'm missing something or misunderstand what you
>> are saying:
>>
>> 1) Given an OutlineModel (or whatever we call it, something being a
>> tree and having per-node tabular data), I think it doesn't make a
>> difference if a node itself or any of its tabular data is edited:
>> the api doc of treeNodesChanged clearly:
>>
>> "Invoked after a node (or a set of siblings) has changed in some
>> way. The node(s) have not changed locations in the tree or altered
>> their children arrays, but other attributes have changed and *may
>> affect presentation*"
>>
>> I think there is no lee-way to not fire: the wrapping model is-a
>> TreeModel and as such must comply to that responsibility. One of
>> The Rules (http://wiki.java.net/bin/view/Javadesktop/SwingLabsImperialRules
>> ) I'm constantly preaching is to not break super's contract, and
>> definitely don't want to be caught doing so myself :-)
>
> That depends if you consider a change columnar

Bad habit of over-editing my emails and then forgetting where I cut/
pasted a word :-)

-> That depends if you consider a change in one row of a non-
hierarchical column == a change in the hierarchical column for that row.

-Tim

> for a row to be a change in the tree node for that row. I would
> argue that unless the change occurred in the tree column, the node
> has not changed, some other cell has. If the change in a non-tree-
> column cell *triggers* a change in the object represented by the
> tree node, then a properly written TreeModel will fire a node change
> as a side effect of the value change.
>
> To make this less hypothetical, say I have a little Swing CRUD
> application using a tree table instead of a table. Column 0 is my
> tree column. My application should change the tree icon of modified
> rows to indicate that a save is needed. I make an edit in column
> 3. Does an edit to column 3 constitute a change in column 0? If
> the TreeModel driving column 0 is properly written, *it* should
> notice the change in the object the node represents and trigger a
> change event and a repaint; I don't believe it is our job to assume
> a change in column 3 constitutes a change in column 0. In this
> example it does (but it's the job of the TreeModel, not us, to
> notice the change); for most uses of a tree table (consider a
> debugger, for example), the visible content of the hierarchical
> column (say, names of variables being that have watches) does not
> change because of a value change in one of the other columns. In
> which case firing a TreeModelEvent just triggers an unnecessary
> repaint and possibly other unnecessary work by other listeners.
>
> So, I'm not saying, don't fire tree model changes if the
> hierarchical column is edited; I'm saying, don't fire tree model
> changes if one of the non-hierarchical columns changes. Re fetching
> a tree path, for the hierarchical column, it should be read-only
> unless there is a way to get a TreePath for the node that would be
> changed; that does not necessarily apply to the other columns.
> However, if your existing TreeTableModel assumes being able to get a
> TreePath when there is a change in any column, then that point is
> somewhat moot.
>
> If an edit is made in the hierachical column, then absolutely,
> treeNodesChanged() should be called. Not doing so would indeed
> break the contract of TreeModel.
>
> If a tree node was *not* the thing that was changed, then, well, the
> tree node didn't change. Ergo the TreeModel didn't change. In which
> case there is no reason for a TreeModelEvent to be fired. If the
> tree node changes as a side-effect of a change in a non-tree column,
> it's the job of the TreeModel to notice that and fire events
> appropriately, not us.
>
>> 2) I might be blind, but I don't see a way to implement a
>> TreePathProvider (which must have a method getPathForNode(Object),
>> not (row), IMO)
>
> Agreed.
>
>> in the general case from the outside - except if I knew that the
>> concrete model has some way to navigate to its parent or walk the
>> tree until I find the node in question. Which ... wouldn't be nice.
>
> I'd expect that most people writing code from scratch *will* extend
> their TreeModel to implement TreePathProvider, creating the
> equivalent of TreeModelExt; but there is the case where someone is
> using a TreeModel supplied by a library (IIRC GlazedLists is like
> this), where extending the TreeModel is not possible, and they
> either need to wrap it or implement path lookup separately (in which
> case they do need to know how to find the path, but it's up to the
> library in question to provide a means to do so - nothing can be
> done about it on our side).
>
> Keeping TreePathProvider independent of TreeModel doesn't sacrifice
> any value, and saves work for those who are being handed a TreeModel
> they didn't create and want to use it in a tree table. Making
> TreePathProvider (nee TreeModelExt) extend TreeModel doesn't add any
> particular value other than making it obviously something that works
> closely with a TreeModel (documentation and method signatures can
> solve that); doing so does, however, make life more difficult for
> people who didn't write the TreeModel they're using. So it seems to
> me the minuses outweigh the pluses for having an extension interface
> to TreeModel.
>
> -Tim
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>


---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net


Kleopatra
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted: Jul 17, 2008 6:46 AM   in response to: Tim Boudreau
  Click to reply to this thread Reply

Tim Boudreau schrieb:
>
> That depends if you consider a change columnar for a row to be a
> change in the tree node for that row. I would argue that unless the
> change occurred in the tree column, the node has not changed, some
> other cell has. If the change in a non-tree-column cell *triggers* a
> change in the object represented by the tree node, then a properly
> written TreeModel will fire a node change as a side effect of the
> value change.
>

I see - then it's a "cultural" thingy: for a SwingX TreeTableModel all
columns are considered as being part of the node. Consequently it must
fire if there's a change in anywhere in the row. Actually, it doesn't
make much of a difference between the hierarchical column and the
others. So the NodeModel - in contrast to your RowModel - covers the
hierarchical column as well as the additional columns.


> To make this less hypothetical, say I have a little Swing CRUD
> application using a tree table instead of a table. Column 0 is my
> tree column. My application should change the tree icon of modified
> rows to indicate that a save is needed. I make an edit in column 3.
> Does an edit to column 3 constitute a change in column 0? If the
> TreeModel driving column 0 is properly written, *it* should notice the
> change in the object the node represents and trigger a change event
> and a repaint; I don't believe it is our job to assume a change in
> column 3 constitutes a change in column 0. In this example it does
> (but it's the job of the TreeModel, not us, to notice the change)

which would make a DefaultTreeModel not properly written or at least
mostly not properly used - never seen a usage where somebody listens to
property changes of the user object <g>. Anyway, I'll stick to SwingX
perspective for now - that is, regard the column properties as part of
the node - and in the wrapping implementation of the TreeTableModel (=
TreeModel + NodeModel) trigger a nodeChanged in the wrapped treeModel. I
think that can be made more flexibly configurable in future, but need to
play a bit more.

For triggering the notification, I added a NodeChangedMediator and a
default implementation which can handle DefaultTreeModels:

/**
 * Helper to trigger tree event notification on a TreeModel after
 * a node content has changed in some way.
 */
public interface NodeChangedMediator {
   
    /**
     * Mediates node change notification for a DefaultTreeModel.
     */
    public final static NodeChangedMediator DEFAULT = new 
NodeChangedMediator() {
 
        @Override
        public void nodeChanged(TreeModel model, Object node) {
            Contract.asNotNull(node, "tree node must not be null");
            Contract.asNotNull(model, "model must not be null");
            if (!(model instanceof DefaultTreeModel))
                throw new IllegalArgumentException("expected model of 
type DefaultTreeModel instead of "
                        + model.getClass().getName());
            DefaultTreeModel treeModel = (DefaultTreeModel) model;
            treeModel.nodeChanged((TreeNode) node);
        }
       
    };
 
    /**
     * Guarantees to trigger a nodeChanged event from the given TreeModel.
     *
     * @param model the TreeModel which contains the node, must not be null.
     * @param node the node which has changed. Must be contained in the 
model,
     *    must not be null.
     * @throws NullPointerException if model or node is null
     * @throws IllegalArgumentException if it can't guarantee the 
notification
     */
    public void nodeChanged(TreeModel model, Object node);
}
 


The wrapping implementation of TreeTableModel now uses that class

a) decide whether the columns are editable (only if it knows a mediator)
b) let it do the notification after setting a columnnar property

    protected boolean isEditable() {
        return mediator != null;
    }
 
    @Override
    public boolean isCellEditable(Object node, int column) {
        return isEditable() && nodeModel.isCellEditable(node, column);
    }
 
    @Override
    public void setValueAt(Object value, Object node, int column) {
        if (!isCellEditable(node, column)) return;
        nodeModel.setValueAt(value, node, column);
        mediator.nodeChanged(treeModel, node);
    }
 


That's used in the XRendererDemo, copied from swinglabs-demos (complete
code in netbeans.xoutline.rendererdemo). Looks okay so far.

Cheers
Jeanette



---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net





 XML java.net RSS