DnD functionality within Docking Frames

Hi All,

I just have a quick general question. I was wondering if anyone had experienced issues with Drag and Drop functionality within their owns screens contained within the Docking Framework.

For example I have a JTree in one of the panels displayed with a Docking Tab. If I drag a tree node and drop it then the entire client freezes. I am guessing the focus on the Docking Client is being lost or consumed by this drag. I cannot select any other tabs in the client and it remains unresponsive.

Any Ideas?

Thanks,

Paul

Hi

Which version of the framework are you using? How is DnD on your JTree implemented?

DockingFrames puts an invisible JComponent over Dockables, maybe this component is consuming all MouseEvents (although there is code present that should prevent exactly your issue). Without any code I can’t tell more.

Hi Beni,

Thanks for the repsonse, below I will try and provide you with some more detailed information on my issue.

Firstly I am using 1.0.8-preview3 version.

I have a tree with the Drag and Drop functionality implemented (outlined below). If I drag from this tree and drop and then try to click on any of the other tabs nothing happens. Its as if the client is frozen.

From debugging the code I can see in the MouseFocusObserver.check(AWTEVENT) that the component is always the tab that contains the tree and not the tab I am selecting with the mouse, hence ultimately the tab changed is always false and I guess that is why it appears to be frozen.

My TreePane implements dragGestureRecognised()


[LEFT]public void dragGestureRecognized(DragGestureEvent e) {
DefaultMutableTreeNode dragNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();[/LEFT]
 
[LEFT]if (dragNode != null) {
Transferable transferable = (Transferable) dragNode.getUserObject();[/LEFT]
 
Cursor cursor = DragSource.DefaultLinkDrop; 
[LEFT]dragSource.startDrag(e, cursor, transferable, this/**tree**/ );[/LEFT]
 
[LEFT]}[/LEFT]
}

[SIZE=2]

[SIZE=2]Any other suggestions?

Thanks Again
[/SIZE][/SIZE]

I have to build me a small test, I’ll answer if/once I find some solution (could take a day or two). In any case this is a serious bug and gets a high priority.

Thanks for the feedback Beni. If you need any further information just let me know.

I need more information. I failed to reproduce the bug. It would be interesting to see what happens, if you run the application below on your machine. Does it work or not?

If it does not work, what JVM are you using, what OS?
If it does work, what is different in my test than in your application?


import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.theme.ThemeMap;

public class DnDTest extends JFrame{
	private DragSource dragSource = new DragSource();
	
	public static void main( String[] args ){
		DnDTest test = new DnDTest();
		test.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		test.setBounds( 20, 20, 400, 300 );
		test.setVisible( true );
	}
	
	public DnDTest(){
		CControl control = new CControl( this );
		control.setTheme( ThemeMap.KEY_ECLIPSE_THEME );
		
		add( control.getContentArea() );
		
		DefaultSingleCDockable data = new DefaultSingleCDockable( "d", "Data", new SourcePanel() );
		control.addDockable( data );
		data.setVisible( true );
		
		DefaultSingleCDockable text = new DefaultSingleCDockable( "t", "Text", new JScrollPane( new JTextArea() ) );
		control.addDockable( text );
		text.setVisible( true );
		
		DefaultSingleCDockable text2 = new DefaultSingleCDockable( "t2", "Text", new JScrollPane( new JTextArea() ) );
		control.addDockable( text2 );
		text2.setLocation( text.getBaseLocation().aside() );
		text2.setVisible( true );
	}

	private class Data implements Transferable{
		private String data;
		
		public Data( String data ){
			this.data = data;
		}
		
		@Override
		public String toString(){
			return data;
		}
		
		@Override
		public Object getTransferData( DataFlavor flavor ) throws UnsupportedFlavorException, IOException{
			return data;
		}

		@Override
		public DataFlavor[] getTransferDataFlavors(){
			return new DataFlavor[]{ DataFlavor.stringFlavor };
		}

		@Override
		public boolean isDataFlavorSupported( DataFlavor flavor ){
			return flavor == DataFlavor.stringFlavor;
		}		
	}
	
	private class SourcePanel extends JPanel implements DragGestureListener, DragSourceListener {
		private JTree tree;

		public SourcePanel(){
			super( new BorderLayout() );
			
			tree = new JTree();
			
			DefaultMutableTreeNode root = new DefaultMutableTreeNode( new Data( "root" ) );
			DefaultMutableTreeNode node1 = new DefaultMutableTreeNode( new Data( "1" ) );
			DefaultMutableTreeNode node2 = new DefaultMutableTreeNode( new Data( "2" ) );
			DefaultMutableTreeNode node3 = new DefaultMutableTreeNode( new Data( "3" ) );
			DefaultMutableTreeNode node4 = new DefaultMutableTreeNode( new Data( "4" ) );
			
			root.add( node1 );
			root.add( node2 );
			root.add( node3 );
			root.add( node4 );
			
			tree.setModel( new DefaultTreeModel( root ) );
			DragGestureRecognizer recognizer = dragSource.createDefaultDragGestureRecognizer( tree, DnDConstants.ACTION_MOVE, this );
			
			add( new JScrollPane( tree ));
		}

		public void dragGestureRecognized( DragGestureEvent e ){
			DefaultMutableTreeNode dragNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();

			if( dragNode != null ) {
				Transferable transferable = (Transferable) dragNode.getUserObject();

				Cursor cursor = DragSource.DefaultLinkDrop;
				dragSource.startDrag( e, cursor, transferable, this );
			}
		}

		@Override
		public void dragDropEnd( DragSourceDropEvent dsde ){
			// TODO Auto-generated method stub
			System.out.println("end");
		}

		@Override
		public void dragEnter( DragSourceDragEvent dsde ){
			// TODO Auto-generated method stub
			System.out.println("enter");
		}

		@Override
		public void dragExit( DragSourceEvent dse ){
			// TODO Auto-generated method stub
			System.out.println("exit");
		}

		@Override
		public void dragOver( DragSourceDragEvent dsde ){
			// TODO Auto-generated method stub
			System.out.println("over");	
		}

		@Override
		public void dropActionChanged( DragSourceDragEvent dsde ){
			// TODO Auto-generated method stub
			System.out.println("drop changed");
		}
	}
}

Hi Beni, I will integrate your panel into my framework to see if I can reproduce the issue and get back to you with what I find.

Thanks for your help on this.

Hi Beni,
regarding your demo (DnDTest) in this thread, I would like to change to a tab while dragging over a tab. How can this be accomplished with 1.1.0?
thanks,
Martin

I have to admit, I did not find an easy and quick solution. I’ll spend some time searching during the weekend.

How important is it for you to use 1.1.0? Can you upgrade to 1.1.2p6? Because that might make my job easier.

Send me a message if I do not answer within a week :wink:

If it is easier with 1.1.2p6 I will try to upgrade.

Alright, I did spend some more time with this issue. In order to find out whether the mouse hovers over a tab I had to modify the framework directly. This means my solution has no chance at all to work with 1.1.0.
On the other hand, if you update to version 1.1.2p7, the tabs will immediately change if you touch them with the mouse during a DnD operation. You need to run the application with Java 1.6 or higher, because Java 1.5 does not tell me where the mouse is during a DnD operation.

I’ve added a TransferHandler (a class called DnDAutoSelectSupport) to all the tabs (well, to the parent of the tabs). This TransferHandler will always say that it cannot import the data - but at the same time it finds out where the mouse is and whether it is currently over a tab. It then forwards an event to a “DndAutoSelectStrategy”, which in return changes the selected Dockable. You can subclass and customize the strategy if you want.

Thanks, the DnD-Functionality works perfect with 1.1.2p7 :slight_smile: