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.
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.
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.
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.
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,
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
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.