The Source for Java Technology Collaboration
User: Password:



Tim Boudreau's Blog

Swing Archives


Egads! An actual Swing Tree-Table!

Posted by timboudreau on June 03, 2008 at 03:36 AM | Permalink | Comments (19)

Four years ago, I went on a hunt for best practices for doing tree table components in Swing. We had a tree-table component in NetBeans, whose maintenance was my never-ending nightmare and the biggest source of bugs on my bug list. It had been written, with the best of intentions, based on Scott Violet's Swing Connection article about how to quickly hack up a tree-table component in Swing (Scott's article was also written with the best of intentions, and I have no intention to ding him here - what he wrote does work for simple use-cases - a debugger is not a simple use-case).

When I canvassed folks who had done Swing tree-tables on our mailing lists, most of them were based on that article, as ours was. What I heard back varied between groans of pain and mad rabid howls of pain. There are a few things in that original tree table design that just don't work - not reliably, anyway. Sending events to an offscreen component as if it were on-screen and expecting it to behave sanely is just a really bad idea that happens to work if the look and feel is a subclass of BasicLookAndFeel, and other look and feel implementations have been tormented into supporting this abuse by all the evil Tree-Table implementations in the wild. But the bottom line is, a look-and-feel author would have to be slightly insane to code their TreeUI to behave as if it were a live component when it has no parent and obviously is not one. In other words, the fact that the JTree-as-cell-renderer design works at all is just an accident of how BasicLookAndFeel's TreeUI implementation was designed, which other look and feels inherited. Never mind trying to use said JTree as a cell renderer in a table (I once made a 400% performance improvement in our tired, tortured, hacked-up TreeTable just by having it translate the graphics context instead of repositioning - and thus causing a re-layout) is seriously abusing the component. Now try convincing said offscreen JTree that it has keyboard focus in order to get it to paint appropriately in its role as a cell renderer for another component. On all look and feels. On all platforms. Everywhere.

You see what I mean.

After doing that canvassing back in '04, it was obvious that Swing needed a real tree-table component. So I started to write one (and the layout cache classes JTree uses were very, very helpful - thanks, Scott!).

I started on it, got the basics working, and then moved back to the U.S., changed jobs and ended up travelling the world full-time teaching other people to write NetBeans modules - but it didn't leave time to finish up the Tree Table work. Thankfully, my former office-mate, David Strupl, picked up where I left off when he left Sun to work on Nokia's NetBeans RCP app for managing cellular telephone networks.

The really, really great news is: This week, Standa Aubrecht - who took over a bunch of the stuff when I left full-time development of NetBeans in '04 and amazed me with how quickly he was able to get going in a complex codebase - committed it into the main line of NetBeans sources yesterday. So anybody who gets a dev build of NetBeans as of today has a perfectly working Swing Tree Table component they can use (the class name is Outline - I borrowed the name from Apple's Cocoa library - it's a little less clunky than "tree table" but gets the point across). The JAR file is org.netbeans.swing.outline.jar. Usage is incredibly easy - you just provide a standard Swing TreeModel of whatever sort you like, and an additional RowModel that can be queried for the other columns contents, editability and so forth. And you never have to worry about cells painted half one color and half another because the tree-cell part got repainted after focus went to a popup menu. It actually works!

The real credit here goes to David and Standa for getting this thing production-worthy - I just was pissed-off enough at having a gargantuan list of unfixable bugs (well, fix it on one platform, break it on another, or leave it unfixed everywhere, or semi-fixed some places - pure evil if you hold the illusion that what we do is computer science) four years ago to get the ball rolling. They're the guys who delivered it.

I'm incredibly happy to see this finally be real and available not just to people writing NetBeans modules, but anybody doing GUI apps in Java. There has been a need for a real, reliable tree table component for Swing programmers for a long, long, long time. All hail David and Standa!

Continuation tooltips for JLists and JTrees

Posted by timboudreau on August 21, 2006 at 02:30 PM | Permalink | Comments (8)

A bit before NetBeans 5.0 was out, I wrote support for completion tooltips for JLists and JTrees for NetBeans' Explorer components. It's not at all NetBeans-specific - it can be used for any JList or JTree.

completionTooltips.png

What it does is relatively simple - provide tooltip-like popup(s) that are painted by the list or tree's cell renderer. If necessary it will provide two tooltips - one on the left, and another on the right.

The source code can be found here - all you do is call

ViewTooltips.register (theComponent);
where theComponent is a JList or a JTree. The code was written in expedience mode, not prettiness mode, but it has been in NetBeans since 5.0, is stable, and pretty useful, as such tooltips are rather slick and nice to have.

Writing it was a bit of an adventure - the basics were simple until I tried the code out on my Mac. There, heavyweight popups have drop shadows- exactly what you don't want around something that is supposed to look like it's part of another component.

badDropShadow.png

There are two solutions to the problem: The simple one, which works 60-70% of the time on Mac - which is just writing a custom PopupFactory which prefers lightweight popups when possible. But this doesn't entirely work, as the mac implementation will sometimes recycle a heavyweight popup. Both can be found here.

The second solution, that works 100% of the time, is the egregious hack (see the aptly named inner class, EgregiousHack with its giant wad of reflection code), which commits the no-no of requiring Apple's Cocoa-Java, digging up the native window using Cocoa via reflection and forcing it to have no shadow. This is disabled by default in NetBeans, as who knows what the fate of Cocoa Java will be, long-term, but can be turned on.

NetBeans@JavaONE - Lookup, API Design and Test Patterns talks at JavaONE, NetBeans Plugin Development at NetBeans Day on Monday

Posted by timboudreau on May 12, 2006 at 10:58 PM | Permalink | Comments (0)

I'm doing way too many talks at JavaONE this year. First and foremost, my friend Jarda Tulach and I will be doing a technical session on Friday afternoon at 2:30PM - How to Design APIs that Stand the Test of Time (TS-6218).

We did a similar talk as a BOF last year, and to our amazement, the room was standing-room-only at 10:30PM with a party with free beer happening next door. Basically what we talk about is tips and techniques we've learned from years of working on NetBeans, making mistakes and learning from them, about what does and doesn't work in API design. And try to address how to be nice to your users while not painting yourself into a corner - how to design for evolution.

On Thursday evening at 7:30PM, we're doing a BOF - Discovery and Dependency Injection Patterns in Modular Architectures (BOF-2559). If you've ever been puzzled by the Lookup API in NetBeans, we hope this talk will make it crystal clear. Basically it's about what a modular architecture is, why it's valuable, and the patterns and libraries we use to enable decoupled components to discover each other at run-time - the Lookup API.

Jarda and Jesse Glick will also be doing a Test Patterns (BOF-0220) talk at 9:30PM on Tuesday night. If you've ever wanted to write JUnit regression tests for unusual things such as deadlocks and memory leaks, this is the talk for you. It will also cover the NbJUnit extensions to JUnit, which provide support for such things, and which are now available from jpackage.org.

And before all this, on Monday at NetBeans Day San Francisco I'll spend two hours presenting how to develop plug-ins for NetBeans and how to use the NetBeans Platform. We'll have a bunch of amazing speakers, some very interesting announcements and a whole lot of fun. NetBeans Day is free to attend, even if you're not going to JavaONE.

I'll also be doing some demos during Charles Ditzel's Twelve Reasons to Use NetBeans talk on Wednesday at 9:45AM - if you haven't caught up on NetBeans 5.0 yet and you can't make it to NetBeans Day, we promise to pack as much as we can into an hour of in-depth demos.

There are a lot more NetBeans-related talks at JavaONE too - I'm just shamelessly plugging ones I'm involved it :-)

It will be a busy but fun week. Then I plan to sleep for a month!

More info



A library for creating Wizards in Swing

Posted by timboudreau on April 17, 2005 at 01:21 PM | Permalink | Comments (25)

I wrote a prototype replacement for the Wizards API in NetBeans - trying very hard to create something clean and easy to use, especially one which didn't require the user of the API to write any more code than absolutely necessary. It's now a project on java.net and I'd love to get some feedback.

The ideas are pretty simple:

  • A wizard does not alter its environment until finish() is called
  • You create a factory for panels. It supplies a list of String IDs for panels, and things call it saying "give me the panel for ID 'foo'".
  • The UI you write puts data the user enters into a Map (listen on a text field, when it changes, call settings.put ("stuffTheUserEntered", theTextField.getText()) and can enable/disable Next/Finish
  • The settings map is handled for you - if the user backs up, settings from the current pane are cleanly removed (it's really a map that delegates to a list of per-panel maps)
  • The UI is pluggable - it comes with a default one (which still needs polishing and localization) - so if you want a different UI, set of buttons, whatever, you have complete freedom to provide a custom implementation
  • Branching and wizards with indeterminate numbers of steps are supported (basically this is conditionally nesting one Wizard inside another, but the convenience class for this makes it painless)

I'm sure it's not perfect yet, and would love to get some feedback. I tried pretty hard to make the javadoc complete and full of examples. You can find the project at wizard.dev.java.net, with the javadoc available as a zip.

How to build Swing with NetBeans

Posted by timboudreau on March 24, 2005 at 10:55 AM | Permalink | Comments (0)

There are now weekly source snapshots of J2SE 6.0 (Mustang) on mustang.dev.java.net; but many people want to just try making some change in Swing. In this post, Bino George of the Swing team tells how to build Swing in NetBeans - so all you do to build it is press F11, and all you do to run SwingSet is press F6.

NetBeans now has Mac-friendly key bindings

Posted by timboudreau on September 08, 2004 at 01:37 PM | Permalink | Comments (7)

I just committed some changes to NetBeans key bindings handling, so that mac users will get key bindings that are much more like other mac apps (no change for Windows or Linux users).

Specifically what's different:

  • Ctrl -> Command - everything that normally maps to Ctrl will use the Command key instead, except where that's impossible (Command-H always hides the app, Command-Q always quits, Command-~ always changes windows, that sort of thing)
  • Command-G maps to Find-Next
  • Command-R maps to Replace (Ctrl-H, the windows key binding, works as well)
  • Cursor control keys in the editor are the default mac ones - Option-Left-arrow to skip to next word, etc. (Option==Alt)

Also, dialog buttons will now appear in the correct order on Macs, with OK on the right.

Alas, these changes will not be in NetBeans 4.0 Beta 2 - I missed the cut-off, but it's better to review things properly than to rush. They will be in Beta 3.

Please give it a try, and let me know if any of your habitual keystrokes are doing the wrong thing. You can download tonight's build here. Be sure to select "Daily" from the "Build Type" drop-down.

The build with these changes will become available just after 4PM PST, or 1AM GMT.



Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds