Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4521075
Votes 239
Synopsis Drag gesture in JAVA different from Windows
Category java:classes_swing
Reported Against 1.4 , 1.4.1 , 1.4.2 , tiger-beta2 , merlin-beta2
Release Fixed mustang(b36), 5.0u5(b02) (Bug ID:2125833)
State 10-Fix Delivered, bug
Priority: 1-Very High
Related Bugs 6265227 , 6341549 , 6342398 , 4380088 , 4425334 , 4803783 , 4817070 , 6524428 , 4501652 , 4673885 , 4765280 , 4832979 , 5052476
Submit Date 30-OCT-2001
Description


 customer  Windows 2000 [Version 5.00.2195]
C:\>java -version
java version "1.4.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta2-b77)
Java HotSpot(TM) Client VM (build 1.4.0-beta2-b77, mixed mode)


Windows Explorer allows starting dragging a node in the file tree in one click
where 2 successive clicks are required in Java 1.4 when the default support for
DnD is enabled for an unselected node in a JTree. I suppose that it would be
the same for any other component with the default DnD support behavior.

If a JTree is used as a source for a drag operation, to drag a node from the
tree, the user needs to click once on the unselected node, release the mouse
button and click a second time, keep the button down to start dragging the node.

With Windows Explorer, if the user clicks on an unselected element and keep the
mouse button down, the user can start dragging that element immediately.
(Review ID: 134499) 
======================================================================
  xxxxx@xxxxx   10/12/04 18:59 GMT
Work Around
N/A
Evaluation

Default drag support for AWT components (Button, List, etc.)
starts a drag operation even if drag gesture was recognized on the
item which wasn't selected before the drag gesture was initiated.
However, several Swing components, including JTree, are
documented to behave by default the different way: they will
initiate the drag only if drag gesture was initiated on selection.

Documentation for JTree.setDragEnabled() says: "When automatic
drag handling is enabled, most look and feels begin a drag-and-drop
operation whenever the user presses the mouse button over a selection
and then moves the mouse a few pixels."  So the observed behavior
matches the documentation.

Anyway, it's up to Swing team to decide if they want their components
to behave this way.  Reassigning to classes_swing.

  xxxxx@xxxxx  


======================================================================

Wow, this is a popular bug. Comitting to tiger.
  xxxxx@xxxxx   2002-10-18

Note that we should also deal with JList and JTable. I am closing a bug on JList as a duplicate of this one.
  xxxxx@xxxxx   2003-01-16

Should investigate 4801246 along with this bug. I beleive they are related.
  xxxxx@xxxxx   2003-01-16

The problem here is clear - our DnD implementation doesn't act as most users would expect. Under many circumstances, a mouse press should select first and then start dragging. One of the problems we need to overcome in order to fix this is the fact that DnD drag gesture recognition is handled in a separate mouse listener than the one that does selection. This is fine for the old behavior since the two mouse listeners don't need much communication - the gesture recognizer processes events first (if something is selected) and consumes them if it doesn't want the selection listener to see them.

In order to correct this bug, there needs to be a lot more communication between the selection logic and the gesture recognition logic. Sometimes a selection needs to happen first. In order to facilitate this, we will collapse the logic down into one listener. Each component will have a single selection listener. The drag gesture recognition code will be moved into a static helper class that the selection listeners can call into _when_appropriate_. Doing it this way allows the event to be seen first by the selection listener, and logic there can then decide whether or not to give the gesture recognition code a chance at the event.

- JTree will be fixed based on this approach.
- JList will be fixed based on this approach.
- JTextComponents will continue to act as before, only starting a drag when something is already selected. This is what is expected for text. However, the text DnD recognition code will be tweaked to use the new helper class.
- JTable will continue to act as before since it is often used in a spreadsheet context. JTable supports dragging to select ranges of cells and therefore it would be wrong to begin a drag unless something is already selected. This is consistent with what other spreadsheet applications do. However - when JTable is used for File selection in JFileChooser, it will be fixed as mentioned above.
  xxxxx@xxxxx   2004-05-11

When JTable is in SINGLE_SELECTION mode (for both rows and columns), it's really being used more like a list component. Therefore, my current thinking is that I'll make it support dragging on the first press (like JTree and JList). We'll have to see how this works out.
  xxxxx@xxxxx   2004-05-18

Note: It looks like I'll be fixing 4501652 as a side effect of fixing this. If so, I'll close that bug as a duplicate when this is done.
  xxxxx@xxxxx   2004-05-18

4501652 will NOT be fixed by this bug. It will be fixed by another fix in tiger. See that bug for details.
  xxxxx@xxxxx   2004-06-10

Unfortunately, the fix for this bug did not make Tiger. We continue to make fixing this bug a major priority and the lack of fix to date certainly does not stem from non-interest. The major problem still to overcome is how to solve this in a way that is backward compatible. One of the issues that was encountered is that JTree and JTable allow customization of what mouse clicks start an edit. With this logic being pluggable, it makes it extremely difficult to write drag detection logic in the correct way. It is my current belief that the fix to this bug will require making some assumptions about what developers might do. Unfortunately, that's not something that was safe so late in Tiger. I continue my efforts...
  xxxxx@xxxxx   10/12/04 18:59 GMT

Fixing this bug is my number one priority for Mustang. I have continued with my previous work and have come even farther. I believe the implementation to be done for JTextComponents, JList and JTable. JTree is next, and I begin work immediately. In order to make JTable work correctly, I had to make some changes in behavior when getDragEnabled() is true:

1) Cell editing will no longer start on mouse presses. It will start only on mouse releases.
2) The value of CellEditor.shouldSelectCell() will be ignored in that cells will always be selected. This is necessary, otherwise they could never be dragged. The method WILL still be called, however, to ensure backward compatibility for those that expect it to be called after editing starts.
  xxxxx@xxxxx   2005-04-21 18:55:17 GMT

I've now completed the implementation for JTree. I've made similar changes to those made in JTable that change the behavior when getDragEnabled() is true. That is, cell editing will start on mouse releases. But it will only start if no selection change was made by the press. This is to remain compatible with DefaultTreeCellEditor. Also, the value of CellEditor.shouldSelectCell() will also be ignored in that cells will always be selected. This is for the same reasons outlined above.

Lastly, as part of this fix, I've also made some changes to the Metal version of JFileChooser. It will now behave much more like the Windows L&F JFileChooser in terms of selection, activation, and drag recognition.
  xxxxx@xxxxx   2005-04-27 16:40:42 GMT

This change will be backported to a 5.0 update release, to be enabled by a system property, "sun.swing.enableImprovedDragGesture". Example:

java -Dsun.swing.enableImprovedDragGesture APP_CLASS_NAME

  xxxxx@xxxxx   2005-05-03 17:15:56 GMT
Comments
  
  Include a link with my name & email   

Submitted On 13-FEB-2002
enicholas
This is extraordinarily lame -- the current behavior is useless.


Submitted On 19-FEB-2002
tgitnick
The observed drag and drop behavior in jdk1.4 is different
from the behavior in jdk1.3, and it is wrong.

A Panel containing buttons which are implement
dragSourceListener no longer get dragGestureRecognized
events until the second click.  After that the buttons are
notified on the first click down until the panel containing
them looses focus.  

This is not a "look and feel" problem that is a style issue
for the swing developers.  This is a bug in the jdk's focus
listener.  

Do not try to pass this off,  I am having to advise users to
refrain from updating their jdk to keep applications working.

Terry Gitnick


Submitted On 23-APR-2002
afeinman
The current implementation makes it extremely difficult to
use Drag and Drop in JTrees and JTables. Specifically, it is
impossible using the basic components to select multiple
items and then begin a drag, as the drag rearranges the
selection in the JTable.

A workaround where, once a drag gesture is recognized,
selection events are ignored, is possible but cumbersome.
Better would be a flag in JTable to allow this behavior (not
selecting once a Drag has been recognized).

The bugs in 1.4 are even more serious, as Terry has pointed out.

Alex


Submitted On 30-APR-2002
jessh
I thought 1.4 was going to make platform-consistent drag-
and-drop behavior easy to achieve, especially in tables and 
trees.  Why does Sun feel it's okay to require special 
workarounds to get multi-select drag-and-drop to work in a 
JTree???


Submitted On 13-MAY-2002
gbishop
Uh, this is not OK.  Make it work like windows.  It's not 
up to the Swing team, it's up to us, and we say, FIX IT.


Submitted On 13-MAY-2002
garyjames
What's the point of having a Windows Look And Feel when it 
doesn't work the same way as Windows?  When users try a 
select-drag operation it will simply not respond and makes 
our software difficult to use and look buggy.  

It's a shame when the Swing Team have put lots of work into 
getting multi-drag working with JTables etc. when problems 
like this make those components unusable.


Submitted On 15-JUL-2002
chuanhaochiu
Right on gbishop!!!  Fix the damn thing Sun!!!

Actually I don't care anymore.

AWT/Swing will never be good enough to base a modern
GUI on.  Not because it couldn't be, but because Sun just
don't care.

Either Sun open source AWT/Swing and let those who care
take a wack at it, or I recommand taking a serious look at
SWT at http://www.eclipse.org/.


Submitted On 07-AUG-2002
uniemimu
I also bumped into this need for a selection before dragging 
from a JTable, but it can be worked around. 

Just create your own DragGestureRecognizer and use that; 
then you don't need to make a selection before you drag. As 
a basis, the 
javax.swing.plaf.basic.BasicDragGestureRecognizer can be 
uselful, also look into the source of BasicTableUI and the 
TableDragGestureRecognizer. 

So much about making a drag without making a prior 
selection.

About multiple selection and dragging multiple items, I also 
don't see the problem. I was just trying with this DIY 
DragGestureRecognizer and DIY TransferHandler. I could 
easily select multiple cells from the JTable and get the info 
from the whole selection when creating the Transferable. 
Granted, the selection disappears after doing this, but I don't 
see that as a problem. So no problems at least with the 
selectionmodel I was using.


Submitted On 11-SEP-2002
salah_elsayed
I think I have found a solution to this problem but I don't 
know if it has side effects or not
any way, here is my thinking

in mouseDragged method I initiated the Drag & Drop process 
by calling exportAsDrag and It works fine
now I can drag an unselected row in JTable. 
but I encountered a new problem which is that when I start 
to drag an unselected row and the pointer of the mouse  
beside the bound between the two rows it drags the two 
rows not the desired row.


Submitted On 01-OCT-2002
Shammah
A freind of mine was coding in VB (6 I assume), and this 'bug' 
behaviour is exactly what is the case in a vb tree.

Someone probably just followed M$ too closely (I'm amazed at 
how clunky VB interfaces can be - they're almost as bad as 
the AWT!)

So even M$ development platforms do not have the 
Windows 'Look and Feel'.

Just thought you should know


Submitted On 29-DEC-2002
simon@tardell.se
There *is* a workaround (or two, one for JList, one for 
JTree). For JList, you want to refire the same mouseEvent 
after the selection has been made. For JTree, you want to 
make sure that the drag starts before the selectionChanged 
event is fired.

For JList, do the following:

	class MyList extends JList {
		MouseEvent myCachedEvent;
		
		protected void fireSelectionValueChanged
(int firstIndex, int lastIndex, boolean isAdjusting) {
			if (myCachedEvent != null) {
			
	super.processMouseEvent(
					new 
MouseEvent(
					
	(Component) myCachedEvent.getSource(),
					
	myCachedEvent.getID(),
					
	myCachedEvent.getWhen(),
					
	myCachedEvent.getModifiers(),
					
	myCachedEvent.getX(),
					
	myCachedEvent.getY(),
					
	myCachedEvent.getClickCount(),
					
	myCachedEvent.isPopupTrigger()));
				myCachedEvent= null;
			}
			super.fireSelectionValueChanged
(firstIndex, lastIndex, isAdjusting);
		}

		
		protected void processMouseEvent
(MouseEvent e) {
			if ((e.getModifiersEx() & 
e.BUTTON1_DOWN_MASK) != 0)
				myCachedEvent= e;
			super.processMouseEvent(e);
		}

	}


for JTree, do the following:
	class DragTree extends JTree implements 
DragGestureListener, DragSourceListener {
		TreeSelectionEvent 
myCachedSelectionEvent;
		public DragTree(TreeModel model) {
			super(model);
			DragSource dragSource= 
DragSource.getDefaultDragSource();

			// creating the recognizer is all 
that's necessary - it
			// does not need to be 
manipulated after creation
		
	dragSource.createDefaultDragGestureRecognizer
(this, // component where drag originates
		
	DnDConstants.ACTION_COPY_OR_MOVE, // actions
			this); // drag gesture listener
			addMouseListener(new 
MouseAdapter() {
				public void 
mouseReleased(MouseEvent e) {
					if 
(myCachedSelectionEvent == null)
					
	return;
				
	DragTree.super.fireValueChanged
(myCachedSelectionEvent);
				
	myCachedSelectionEvent= null;
				}
			});
		}


Submitted On 24-FEB-2003
erikusuma
the current drag n drop should be fixed. my customers are 
keep asking the differences of the behavior in windows.
Please fix it immediately!

Eriawan


Submitted On 14-MAR-2003
scmorr
In JTable for example this happens because mouse events are 
processed first by TableDragGestureRecognizer and then by 
MouseInputHandler (all in BasicTableUI).
Unfortunately we cann't change the order of adding of these 
listeners in our UI, because "defaultDragRecognizer" has 
private access.
So workaround is to copy all code from BasicTableUI (and 
BasicDragGestureRecognizer) or uninstall private listener like 
this:

	protected Object 
searchForTableDragGestureRecognizer() {
		MouseListener[] allMouseListeners = 
table.getMouseListeners();
		for (int i = 0; i < allMouseListeners.length; 
i++) {
			if 
("TableDragGestureRecognizer".equals(allMouseListeners
[i].getClass().getName())) {
				return allMouseListeners
[i];
			}
		}
		return null;
	}

For guaranteed order of listener's invoking we can use "proxy"-
like approach.


Submitted On 22-APR-2003
asjf
is there a Swing team at sun anymore?


Submitted On 02-MAY-2003
andi_edds
This bug should be fixed ASAP.

We especially need correct behavior for JTable


Submitted On 08-MAY-2003
sky_1071
YES! We (the Swing team) are here and listening!
With a 118 votes (currently) we will do our best to get this
fixed asap!


Submitted On 22-JUL-2003
iambart
Glad to hear something is being done about this.  It sucks my 
will to live. :-)


Submitted On 01-AUG-2003
dfasjrweqotr
For a workaround, read my post from Aug 2002 and the 
details for how to do it, which Scmorr provided later for those 
who can't code.. Maybe simon's workaround works too..


Submitted On 12-NOV-2003
herrmsa
I cannot believe it takes that long to close that one.


Submitted On 14-DEC-2003
charlie76
It would be cool if you refactored the BasicUI 
components so that they didn't have private static inner 
classes that implemented this behavior.  At least make 
them protected so that we can subclass and change 
this behavior and fix these types of problems.  Also 
give us a protected method so that we can control 
creation from a subclass of BasicUI components.  
Please Please Please pay attention to these 
suggestions.  Swing currenly makes you rewrite lots of 
perfectly fine code just to change one thing like this.  It 
would help if Swing engineers didn't write methods 
with 400 lines of code in them.  That way we can 
change behavior and still reuse more of their code.


Submitted On 14-DEC-2003
davidbrowne
I am working with dragging an item between 2 JLists (single
selection mode), and both Simon's solution and  scmorr's
(where I remove the private drag gesture recognizer from the
middle and add it at the end) work for me, to a point.  I am
also trying to enforce that only one of my 2 lists can have
a selection at any given time, using a
ListSelectionListener, paying attention to events only if
getValueIsAdjusting() is true.  

The problem comes if you abort a drag and then select an
item in the other list that you weren't dragging from.  When
you drag, the list you drag from doesn't get a
setValueIsAdjusting(false) since you don't get the
mouseReleased() from MouseInputHandler, and leaving the list
in "isAdjusting == true"-mode when a drag is aborted makes
my selection stuff not work.  My solution was to explictly
call comp.setValueIsAdjusting(false) in my exportDone()
function of my custom TransferHandler.  Now everything is cool. 


Submitted On 25-JAN-2004
fancellu2004
ASAP? Still not fixed. Sun really think if they fix a bug 
within 3 years they're superheroes. If they worked 
anywhere else they'd be sacked, only at Sun can a 
team suck so hard for years on end.


Submitted On 04-FEB-2004
untilted
I want to work for Sun...


Submitted On 28-FEB-2004
JessHolle
Java 2 v1.5 beta is out and this is not fixed in it?  I 
thought this was commited to "tiger" and that "tiger" 
was Java 2 v1.5...

As others have pointed out it has been almost 3 years!


Submitted On 10-APR-2004
will_sargent
Ah... so this is why I can't figure out what I'm doing wrong
in my drag and drop...


Submitted On 19-JUN-2004
rexguo
I sincerely urge the Swing team to fix this.
It is things like this that make it hard to make desktop apps that can compete with native windows apps.


Submitted On 21-JUN-2004
Lyle_Z
I have found the source of this bug for JLists, after about 2 days of having to reproduce code due to (in my opinion) superfluous use of the keyword "private". Anyway, the problem is in BasicListUI.java, in the isDragPossible method. Specifically, in the 1.5 beta release, BasicListUI.java beginning on line 2201, is the following statement:

if ((row != -1) && list.isSelectedIndex (row)){
    return true;
}

If this condition is not true, the function returns false, and this is what prevents the drag operation from being possible without first clicking and releasing on the list item to be dragged.

The problem is that the list is not yet marked as being selected, and so the call to list.isSelectedIndex(row) returns false. I fixed this by replacing this single if-statement with the following statements:

if (row == -1)
    return false;
else if (list.isSelectedIndex (row))
    return true;
else{
    list.setSelectedIndex (row);
    return true;
}

I have tested this, and it works.

BTW, I feel that the keyword "private" should be abolished. It does nothing to enhance security, as my successful, albeit laboreous attempt to circumvent the private keyword via much cutting and pasting proves, and it just makes life harder. Its as if to say, no other developer can be trusted with my code, they're not at smart as I. As recent years of shown, real security threats come from vulnerabilities in operating systems, not from allowing someone to actually make use of available source code.

Sincerely

Lyle Ziegelmiller
lyle_z@hotmail.com


Submitted On 21-JUN-2004
herrmsa
It is submitted as P1 bug for Tiger. So I think we can safely assume that it will be fixed.


Submitted On 05-OCT-2004
durech
What happened to this defect?  It was scheduled for 1.5 (aka 5.0) and listed as a P1 bug that was supposed to be corrected. I noticed somewhere around the 2nd beta, it quietly just disappeared from the P1 bugs committed to tiger.  When will this problem ever get fixed????


Submitted On 20-OCT-2004
arambaut
The following code allows you to drag select in a table but if the drag originates in a previously selected cell, then it starts a drag-and-drop without changing the selection:

class MyTable extends JTable {

	public MyTable() {
		setUI(new MyTableUI());
	}

	class MyTableUI extends BasicTableUI {

		protected MouseInputListener createMouseInputListener() {
			return new MyMouseInputHandler();
		}

		class MyMouseInputHandler extends MouseInputHandler {
			public void mousePressed(MouseEvent e) {
				Point origin = e.getPoint();
				int row = table.rowAtPoint(origin);
				int column = table.columnAtPoint(origin);
				if (row != -1 && column != -1) {
					if (table.isCellSelected(row, column)) {
						e.consume();
					}
				}

				super.mousePressed(e);
			}
		}
	}
};


Submitted On 06-DEC-2004
sqrammi@hotmail.com
This bug is still an issue in 1.5 final.  Bugs like this really make me which Java was open-source so that simple bugs like this could be fixed much sooner.  How many people are used to the way that Java drags 'n drops anyway (forcing you to click to select, then click to drag)?  Every operating system and toolkit I know acts DIFFERENTLY than Swing does on this issue, don't I think it's of any importance to ensure backwards-compatibility.


Submitted On 29-MAR-2005
mr_gotu
WORK AROUND:

Extend JTree:

public class MyTree extends JTree{
    // single selection-dnd hack: override setUI() and call this method after super.setUI();
    protected void hackSingleSelectionDND(){
        MouseListener dragListener = null;

        // the default dnd implemntation requires to first select node and then drag
        try{
            Class clazz = Class.forName(


Submitted On 29-MAR-2005
mr_gotu
WORK AOUND:

public class MyTree extends JTree{
    // single selection-dnd hack: override setUI() and call this method after super.setUI();
    protected void hackSingleSelectionDND(){
        MouseListener dragListener = null;

        // the default dnd implemntation requires to first select node and then drag
        try{
            Class clazz = Class.forName("javax.swing.plaf.basic.BasicDragGestureRecognizer");
            MouseListener[] mouseListeners = getMouseListeners();
            for(int i = 0; i<mouseListeners.length; i++){
                if(clazz.isAssignableFrom(mouseListeners[i].getClass())){
                    dragListener = mouseListeners[i];
                    break;
                }
            }

            if(dragListener!=null){
                removeMouseListener(dragListener);
                removeMouseMotionListener((MouseMotionListener)dragListener);
                addMouseListener(dragListener);
                addMouseMotionListener((MouseMotionListener)dragListener);
            }
        } catch(ClassNotFoundException e){
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }
    
    public void setUI(TreeUI ui){
        super.setUI(ui);
        hackSingleSelectionDND();
    }
}


Submitted On 27-MAY-2005
javaguyaimfi
Even better work around for JTree. If you're using the built in dnd support for JTree (setDragEnabled(true)) you can simple export a drag whenever you wish. Here's a simple example piece of code 'inside' a custom MyJTree. Single selection drag with both mouse buttons with 750ms delay
// --------------------------------------- //
private int mouseButtonDown = MouseEvent.NOBUTTON;
  private long mouseButtonDownSince = 0;
  private void initCustomDragGestureRecognizer()
  {
    addMouseListener(new MouseAdapter()
    {
      public void mousePressed(MouseEvent e)
      {
        mouseButtonDownSince = System.currentTimeMillis();
        mouseButtonDown = e.getButton();
      }
      public void mouseReleased(MouseEvent e)
      {
        mouseButtonDown = MouseEvent.NOBUTTON;
      }
    });
    addMouseMotionListener(new MouseMotionAdapter()
    {
      public void mouseDragged(MouseEvent e)
      {        
        if (mouseButtonDown != MouseEvent.NOBUTTON && (System.currentTimeMillis() - mouseButtonDownSince) > 750)
        {
          if (getPathForLocation(e.getX(), e.getY()) != null)
            getTransferHandler().exportAsDrag(MyJTree.this, e, DnDConstants.ACTION_COPY);
        }
        else
          mouseButtonDown = MouseEvent.NOBUTTON;
      }
    });
  }
// --------------------------------------- //


Submitted On 28-MAY-2005
joewalp
This is on the recently closed bugs page [1], but its state is "in progress, bug".  Is it closed?

[1]
http://bugs.sun.com/bugdatabase/recently_closed.do


Submitted On 07-JUN-2005
shan-man
Yes, this bug is in fact closed and fixed! And a backport is on the way for J2SE 5.0 update 5. Please see my weblog for more details: http://weblogs.java.net/blog/shan_man/archive/2005/06/improved_drag_g.html


Submitted On 01-SEP-2006
rob@netplay.co.uk
Hmm, I had problems on 5.0 update8 and 6 beta 2. 

I have to do this

http://forum.java.sun.com/thread.jspa?messageID=4363202



PLEASE NOTE: JDK6 is formerly known as Project Mustang