JDK-5101182 : Cursor not modified during Drag and Drop
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: solaris_10
  • CPU: x86
  • Submitted: 2004-09-13
  • Updated: 2004-09-24
  • Resolved: 2004-09-24
Related Reports
Relates :  
Description
Java Version: 1.5.0-rc-b63
Platform: Solaris10_b66-IAx86 with JDS release 3(cinnabar-b16)

The problem:
When initiating a DnD operation within a JTree, the JTree acts as both a
source and a target.  When the JTree rejects the drag, the cursor should change
to the NoDrop cursor, but does not.  If you hit the Shift key, the
DropTargetListener receives the "dropActionChanged" message and the cursor is
properly changed to the NoDrop cursor.

Please see bug4407521 which fixed in mantis.
But the problem only happens in IA10_b66 with JDS, sparc10_b66(JDS) is ok. Other platfroms are OK too.

To reproduce:
using b63 java to compile and run DndTree.java

The code is as followings:
// ~~~~~~~~~~~~~~~~~  code sample follows  ~~~~~~~~~~~~~~~~~~~~
//

/**
The following test program demonstrates several cursor problems in the DnD
system.

Try dragging a "true" node within the tree.  The drag is rejected by the
DropTargetListener, but the cursor never changes to the NoDrop cursor!

Also, the DragSourceListener only receives the "dragEnd" and "dragDropEnd"
messages, never the "dragEnter" or "dragOver" messages.

Lastly, the cursor never changes when you drag over a component (JLabel
or JButton) with no associated DropTarget.  Shouldn't the cursor change
to the NoDrop cursor?
*/

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;

import javax.swing.*;
import javax.swing.tree.*;


public class DndTree extends JPanel
{
   /** scrollpane to display tree */
   protected JScrollPane scrollPane = new JScrollPane();

   /** JTree displaying the server */
   protected JTree serverTree = new JTree();

   /** root node of the tree */
   protected DefaultMutableTreeNode root;

   /** tree model */
   protected DefaultTreeModel model;

   // DND related vars
   protected DragSource          myDragSource;
   protected DndSourceHandler    dndSource;
   protected DndTargetHandler    dndTarget;
   protected DropTarget          myDropTarget;

   /**
    * Constructor.
    */
   public DndTree()
   {
      try
      {
         jbInit();
      }
      catch(Exception ex)
      {
         System.out.println(ex);
      }

      root = new DefaultMutableTreeNode("root");

      // give the tree a model using root
      model = new DefaultTreeModel(root);
      serverTree.setModel(model);

      // add some child nodes
      model.insertNodeInto(new DefaultMutableTreeNode(new Boolean(true)), root,
0);
      model.insertNodeInto(new DefaultMutableTreeNode(new Boolean(false)), root,
0);
      model.insertNodeInto(new DefaultMutableTreeNode(new Boolean(false)), root,
0);
      model.insertNodeInto(new DefaultMutableTreeNode(new Boolean(true)), root,
0);

      // set other tree display properties
      serverTree.putClientProperty("JTree.lineStyle", "Angled");
      serverTree.setShowsRootHandles(true);
            serverTree.getSelectionModel().setSelectionMode(
                                     TreeSelectionModel.SINGLE_TREE_SELECTION);

      // setup DND for dragging IElements into the Task Editor
      myDragSource = new DragSource();
      dndSource = new DndSourceHandler();
      myDragSource.createDefaultDragGestureRecognizer(serverTree,
                                         DnDConstants.ACTION_MOVE, dndSource);

      // setup DND target to receive drags within tree
      dndTarget = new DndTargetHandler();
      myDropTarget = new DropTarget(serverTree, dndTarget);

   }

   private void jbInit() throws Exception
   {
      this.setLayout(new BorderLayout());
      this.add(new JLabel("just some text", JLabel.CENTER), BorderLayout.NORTH);
      this.add(scrollPane, BorderLayout.CENTER);
      this.add(new JButton("RIGHT"), BorderLayout.EAST);
      this.add(new JButton("LEFT"), BorderLayout.WEST);
      scrollPane.getViewport().add(serverTree, null);

   }

   /**
    * Allows the JTree to act as a drag source
    */
   private class DndSourceHandler implements DragSourceListener,
DragGestureListener
   {
      /**
       */
      public void dragGestureRecognized(DragGestureEvent dge)
      {
         TreePath path = serverTree.getSelectionPath();
         if (null == path)
            return;

         DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                                       path.getLastPathComponent();
         Boolean b = (Boolean) node.getUserObject();
         if ( b.booleanValue() == true ) {

            // create an object to contain our data
            Transferable t = (Transferable) new StringSelection(b.toString());

            // start the DnD drag operation
            myDragSource.startDrag(dge, DragSource.DefaultLinkDrop, t,
                                   DndSourceHandler.this);
            System.out.println("source starting drag!");
         }
      }
      public void dragEnter(DragSourceDragEvent dsde) {
         System.out.println("source dragEnter: " + dsde.getTargetActions());
      }
      public void dragExit(DragSourceEvent dse) {
         System.out.println("source dragExit: " +
                            dse.getDragSourceContext().getCursor().toString());
      }
      public void dragDropEnd(DragSourceDropEvent dsde) {
         System.out.println("source dragDropEnd: " + dsde.getDropAction());
      }
      public void dragOver(DragSourceDragEvent dsde) {
         System.out.println("source dragOver: " + dsde.getTargetActions());
      }
      public void dropActionChanged(DragSourceDragEvent dsde) {
         System.out.println("source dropActionChanged: " +
                            dsde.getTargetActions());
      }

   }

   /**
    * Allows JTree to act as a drop target
    */
   protected class DndTargetHandler implements DropTargetListener {
      public void dragEnter(DropTargetDragEvent dtde) {
         System.out.println("target rejecting drag!");
         dtde.rejectDrag();
         System.out.println("target dragEnter: " + dtde.getDropAction());
      }
      public void dragOver(DropTargetDragEvent dtde) {
      }
      public void drop(DropTargetDropEvent dtde) {
         // reject the drop
         System.out.println("target rejecting drop!");
         dtde.rejectDrop();
         System.out.println("target dragEnter: " + dtde.getDropAction());
      }
      public void dragExit(DropTargetEvent dte) {
         System.out.println("target dragExit: " +
dte.getDropTargetContext().getComponent().
                            getCursor().toString());
      }
      public void dropActionChanged(DropTargetDragEvent dtde) {
         System.out.println("target dropActionChanged: " +
                             dtde.getDropAction());
      }
   }


   //
   //
   //          TESTING ONLY !!
   //
   //
   static public void main(String[] argv) {
      // create a frame
      final JFrame frame = new JFrame("DndTree Frame");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(300, 200);
      frame.setLocation(350, 250);
      frame.setVisible(true);
      // create a dialog based on the frame
      JDialog dialog = new JDialog(frame, "DnD Tree Tester", true);
      dialog.getContentPane().setLayout(new BorderLayout());
      dialog.setSize(new Dimension(400, 350));
      dialog.setLocation(300, 200);
      dialog.setResizable(true);
      // add the tree panel to the dialog
      DndTree panel = new DndTree();
      dialog.getContentPane().add(panel, BorderLayout.CENTER);
      dialog.setVisible(true);
   }

}

Comments
EVALUATION The test case given in the description mixes Swing DnD support and direct AWT DnD support. Usage of direct AWT DnD support with Swing components is discouraged. Refer to the bugs 4449146, 4380088, 4950103 and 4989414 which caused by the mixing. Please provide a pure AWT test case. ###@###.### 2004-09-15 Well, I asked to provide a valid test case, but to save the tester's time I'll evaluate the bug. Luckily, usage of direct AWT DnD support for Swing components isn't an issue in this case. Since non-null cursor is passed to startDrag(), the cursor isn't updated during the DnD operation. This is reproducible on all platforms with JDK1.5.0-b62. Does the submitter really observe different behavior? Refer to the bug 5102378 (Clarify default drag cursor behavior in startDrag() methods) which explains the situation with change of the cursor during a DnD operation. If null cursor is passed to startDrag() then it's changed to NoDrop as the drop target rejects the drag. If the submitter agrees with the above evaluation, I'll close the bug. ###@###.### 2004-09-17 The submitter has agreed with the above evaluation, so I'm closing this report as not a bug. ###@###.### 2004-09-24
17-09-2004