|
Replies:
34
-
Last Post:
Jul 17, 2008 6:46 AM
by: Kleopatra
|
|
|
|
|
|
|
Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 9, 2008 5:36 AM
|
|
|
.. 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
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 9, 2008 5:38 AM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 9, 2008 1:47 PM
in response to: Kleopatra
|
|
|
I really appreciate the work you do fixing core bugs and promoting correct practices. Thank you.
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 9, 2008 10:35 PM
in response to: Kleopatra
|
|
|
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.
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 9, 2008 11:40 PM
in response to: rturnbull
|
|
|
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
|
|
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 10, 2008 12:45 AM
in response to: rturnbull
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 11, 2008 8:19 AM
in response to: rturnbull
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 10, 2008 12:19 PM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 11, 2008 12:52 AM
in response to: timboudreau
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 11, 2008 10:16 AM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 11, 2008 10:32 AM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 11, 2008 10:37 AM
in response to: timboudreau
|
|
|
[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񅵣 - 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]
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 14, 2008 4:43 AM
in response to: timboudreau
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 14, 2008 6:31 AM
in response to: Kleopatra
|
|
|
> 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񁦉
I just looked and it's probably not good, since I failed to file a bug. 
Karl
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 14, 2008 7:04 AM
in response to: Kleopatra
|
|
|
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.
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 5:19 AM
in response to: david_hall
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 6:56 AM
in response to: Kleopatra
|
|
|
> 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.
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 7:22 AM
in response to: david_hall
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 10:01 AM
in response to: david_hall
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 10:57 AM
in response to: Tim Boudreau
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 16, 2008 1:32 AM
in response to: Tim Boudreau
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 14, 2008 8:19 AM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 5:38 AM
in response to: Tim Boudreau
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 4:21 AM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 5:46 AM
in response to: Kleopatra
|
|
|
> 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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 7:45 AM
in response to: kschaefe
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 8:08 AM
in response to: Kleopatra
|
|
|
> 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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 15, 2008 9:29 AM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 16, 2008 2:13 AM
in response to: Tim Boudreau
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 16, 2008 7:11 AM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 16, 2008 8:08 AM
in response to: Tim Boudreau
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 16, 2008 9:09 AM
in response to: Kleopatra
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 16, 2008 9:25 AM
in response to: Tim Boudreau
|
|
|
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
|
|
|
|
|
|
|
|
Re: Sneak Preview: new SwingX JXTreeTable - queen-quality
Posted:
Jul 17, 2008 6:46 AM
in response to: Tim Boudreau
|
|
|
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
|
|
|
|
|