Improved Drag Gesture in Swing
One small step for Shan, one exciting leap for Swing drag and drop.
Fantastic! The java.net folks kindly set me up a place to share my thoughts,
I sit down and begin typing, and out comes a play on the monumental
Neil Armstrong quote.
I consider: "Why would I start my blog space with a goofy play on
words, appearing to compare Swing drag and drop to humankind landing on the moon?" Well,
the answer is twofold: First, as a software engineer, my mind often travels into
odd or complex places, and seems to stick there for extended periods of time
(like the months I disappeared into fixing the drag and drop bug which I'm about
to tell you about). Driving to work this morning, thinking about how to start off this
blog that I've been planning for some time, in popped the "One small step..." jingle.
As I've just described, I got stuck on it. Although I got a kick out of my own [not so]
wittiness, I realized it was rather cheezy. So I tried playing a game with myself to pass the
commute - if I could forget about it by the time I arrived at work, I'd find something else
to start with. You know how successful trying to forget about something can be...
But the more important reason I started as I did is that it perfectly summarizes this morning
for me. I'm taking my very first step into the world of blogging, and to mark the occasion
I'm announcing a very exciting bug fix to Swing drag and drop. While I wouldn't even think
to seriously compare this to landing on the moon, I know it will mean the world to a rather
large group of Swing drag and drop users.
Until very recently, the sixth highest vote getter on Sun's list of
Top 25 Bugs was bug
4521075 with a
total of 239 votes. This bug reports that the recognition of a drag gesture
in Swing is unlike what is typically expected by users. More specifically, it complains
that Swing requires an item to first be selected with one mouse click,
before pressing on it again and dragging to begin drag and drop. The much more
common paradigm expected by users is that a single mouse press should be able
to select the item and also begin recognition of a drag gesture.
I am extremely pleased to announce that this important bug has been fixed! In fact,
it has already been released to the public in build 36 of Mustang, which you can
download now. And let me top this with
some even better news: This fix is also targeted to be released in update 5 of
J2SE 5.0, due out in the not too distant future.
Originally, the fix for this bug was targeted to be the default behavior in FCS of
J2SE 5.0. However, it turns out that the changes involved were larger and had
more potential for backward incompatibility than was orginally expected. It was a
sad thing to do after all of the effort we'd invested, but we finally decided that this
needed more investigation to eliminate the risk of breaking existing
applications, and therefore it couldn't make 5.0. But that's history!
Today, the fix is available in Mustang with very few potential points of
incompatibility, and we'll make the entire fix available in 5.0 update 5
safely by conditionalizing around a system property,
sun.swing.enableImprovedDragGesture". So in update 5 you'd launch
your application like this:
java -Dsun.swing.enableImprovedDragGesture APPCLASSNAME
(In Mustang the system property disappears and it just works!)
Most of the details regarding this fix are available in the evaluation of the bug report.
But please let me point out the highlights:
JFileChooserhave been fixed
such that a selection is no longer required before pressing on an item to begin a drag operation.
More importantly, we've carefully studied this behavior and are confident that the many
different combinations of mouse gestures will work as expected
(ex. ctrl-press, ctrl-press then drag, etc).
JTablehas also been fixed to work as described, but (for good reason) only
SINGLE_SELECTIONmode. The reason behind this decision is that
has always allowed the user to select ranges of cells by dragging the mouse.
The new drag gesture would be identical to the existing gesture for selecting a range of
cells, and this conflict prevented the change from being be made in modes supporting
multiple selections. In these modes, users must continue to select a range of cells first,
before clicking on them to start drag and drop. This behavior is consistent with the
spreadsheet applications we compared with during development.
Of course, the description of this change wouldn't be complete without a quick summary
of any potential points of incompatibility:
Consolidation of selection and gesture recognition logic:
Prior to this fix, selection logic and drag gesture recognition logic was separated
into two distinct mouse listeners installed by the UI on each component. The two listeners
knew nothing about each other, and therefore it wasn't possible to make them do the
right thing. In some cases selection needs to happen before considering for a drag
gesture, and in other cases drag and drop should begin without processing selection
changes. Without coordination between the two listeners, this process couldn't work.
The fix was to put all selection and
drag gesture recognition logic into a single mouse listener to be installed
by the UI on each component. This has worked extremely well and has facilitated the fix of this
bug as desired. It has also introduced the first two very minor points of potential
incompatibility. First, I have seen numerous work-arounds posted to forums for this bug,
and some of them include removing or playing with the private listeners on the components.
It is unknown how these work-arounds will fare under the re-designed drag recognition.
The good news is that any problem can be easily fixed by removing the work-around.
The second potential for incompatibility is for developers that have created custom UI
implementations supplying their own mouse listeners that replace the behavior of Swing's
Any such implementation would simply suffer from no longer having built-in drag support. We
don't expect this to be a major issue though, as most UIs replace the look of a component and leave
the listeners alone.
Handling of cell editors:
The last thing of significance that had to be modified to facilitate this change is the way
that cell editors are handled in
JTreewhen drag recognition
is turned on. While selection and drag recognition will be considered on mouse press events,
cell editing will now not be considered until after the mouse has been released. This will not affect
most developers at all (after the mouse release, Swing re-processes the press event - and things
will appear to developer code the same as before). The only easily noticeable result of this is
JTablesnow pop up on the release rather than
the press. This is considered a benefit in that users can now begin drag and drop
or drag to make selections on top of a
JComboBoxcell without it popping up. Finally,
the value of
CellEditor.shouldSelectCell()will now be ignored for table
and tree editors when drag is enabled, on the grounds that cells that aren't selected
can never be dragged.
Phew, that covers it! I can't believe I let my mind back into those last couple of points again.
But seriously folks, I absolutely love working on Swing drag and drop and there's some more
exciting changes in the works that I'll be writing about shortly. So please, if you're interested
in Swing drag and drop, Swing in general, or cheesy plays on words, please come back and visit soon.
Otherwise, life would really be a drag. Ha ha h...OK, I think it's about time I drop it.