/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.explorer.view; import java.util.TooManyListenersException; import java.awt.dnd.*; import java.awt.Point; import java.awt.Dialog; import java.awt.datatransfer.Transferable; import java.io.IOException; import javax.swing.JComponent; import javax.swing.SwingUtilities; import javax.swing.tree.*; import org.openide.nodes.Node; import org.openide.ErrorManager; import org.openide.util.Utilities; /** Support for the drag operations in explorer. * * @author Jiri Rechtacek */ abstract class ExplorerDragSupport implements DragSourceListener, DragGestureListener { // Attributes /** True when we are active, false otherwise */ boolean active = false; /** Recognizes default gesture */ DragGestureRecognizer defaultGesture; /** The component which we are supporting (our client) */ protected JComponent comp; ExplorerDnDManager exDnD = ExplorerDnDManager.getDefault (); /** Initiating the drag */ public void dragGestureRecognized (DragGestureEvent dge) { // 1. get seleced dragged nodes Node[] nodes = obtainNodes(dge); // check nodes if ((nodes == null) || (nodes.length == 0)) { return; } // 2. detect highest common action int possibleAction = DnDConstants.ACTION_MOVE; for (int i = 0; i < nodes.length; i++) { if (possibleAction == DnDConstants.ACTION_MOVE) { if (!nodes[i].canCut ()) { possibleAction = DnDConstants.ACTION_COPY; } } if (possibleAction == DnDConstants.ACTION_COPY) { if (!nodes[i].canCopy ()) { possibleAction = DnDConstants.ACTION_NONE; } } } exDnD = ExplorerDnDManager.getDefault (); exDnD.setAllowedDragActions (possibleAction); int dragAction = dge.getDragAction(); boolean dragStatus = canDrag (dragAction, possibleAction); // 3. get transferable and start the drag try { // for MOVE Transferable transferable; if (possibleAction == DnDConstants.ACTION_MOVE) { // for MOVE transferable = DragDropUtilities.getNodeTransferable(nodes, DnDConstants.ACTION_MOVE); exDnD.setDraggedTransferable (transferable, true); // for COPY too transferable = DragDropUtilities.getNodeTransferable(nodes, DnDConstants.ACTION_COPY); exDnD.setDraggedTransferable (transferable, false); } else if (possibleAction == DnDConstants.ACTION_COPY) { // for COPY transferable = DragDropUtilities.getNodeTransferable(nodes, DnDConstants.ACTION_COPY); exDnD.setDraggedTransferable (transferable, false); } else { // transferable for NONE transferable = Node.EMPTY.drag (); exDnD.setDraggedTransferable (transferable, false); } //System.out.println("Transferable: " + transferable); // NOI18N exDnD.setDraggedNodes (nodes); Dialog d = (Dialog)SwingUtilities.getAncestorOfClass (Dialog.class, comp); if (d != null && d.isModal ()) { exDnD.setDnDActive (false); return ; } else { exDnD.setDnDActive (true); dge.startDrag( DragDropUtilities.chooseCursor (dragAction, dragStatus), Utilities.loadImage( "org/openide/resources/cursorscopysingle.gif"), // NOI18N new Point (16, 16), transferable, this ); } } catch (InvalidDnDOperationException exc) { // cannot start the drag, notify as informational ErrorManager em = ErrorManager.getDefault (); em.notify (ErrorManager.INFORMATIONAL, exc); exDnD.setDnDActive (false); } catch (IOException exc) { // cannot start the drag, notify user ErrorManager.getDefault ().notify (exc); exDnD.setDnDActive (false); } } private boolean canDrag (int targetAction, int possibleAction) { switch (possibleAction) { case DnDConstants.ACTION_MOVE: return true; case DnDConstants.ACTION_COPY: case DnDConstants.ACTION_COPY_OR_MOVE: case DnDConstants.ACTION_LINK: return (targetAction!=DnDConstants.ACTION_MOVE); default: return (possibleAction!=DnDConstants.ACTION_NONE); } } public void dragEnter (DragSourceDragEvent dsde) { dsde.getDragSourceContext().setCursor(DragDropUtilities.chooseCursor( dsde.getDropAction (), canDrag(dsde.getUserAction (), exDnD.getAllowedDragActions ()))); } public void dragOver (DragSourceDragEvent dsde) { dsde.getDragSourceContext().setCursor(DragDropUtilities.chooseCursor( dsde.getDropAction (), canDrag(dsde.getUserAction (), exDnD.getAllowedDragActions ()))); } public void dropActionChanged (DragSourceDragEvent dsde) { } public void dragExit (DragSourceEvent dse) { dse.getDragSourceContext().setCursor( DragDropUtilities.chooseCursor( dse.getDragSourceContext ().getSourceActions (), false)); } public void dragDropEnd (DragSourceDropEvent dsde) { // not transferable for MOVE nor COPY exDnD.setDraggedTransferable (null, true); exDnD.setDraggedTransferable (null, false); // no nodes are dragged exDnD.setDraggedNodes (null); // no drop candidate NodeRenderer.dragExit (); } /** Activates or deactivates Drag support on asociated JTree * component * @param active true if the support should be active, false * otherwise */ public void activate (boolean active) { if (this.active == active) return; this.active = active; DragGestureRecognizer dgr = getDefaultGestureRecognizer(); if (active) { dgr.setSourceActions (exDnD.getSupportedDragActions ()); try { dgr.removeDragGestureListener(this); dgr.addDragGestureListener(this); } catch (TooManyListenersException exc) { throw new IllegalStateException("Too many listeners for drag gesture."); // NOI18N } } else { dgr.removeDragGestureListener(this); } } /** Safe getter for default gesture<br> * (creates the gesture when called for the first time) */ DragGestureRecognizer getDefaultGestureRecognizer () { if (defaultGesture == null) { DragSource ds = DragSource.getDefaultDragSource(); defaultGesture = ds.createDefaultDragGestureRecognizer( comp, exDnD.getSupportedDragActions (), this); } return defaultGesture; } /** Utility method. Returns either selected nodes in tree * (if cursor hotspot is above some selected node) or the node * the cursor points to. * @return Node array or null if position of the cursor points * to no node. */ abstract Node[] obtainNodes (DragGestureEvent dge); } /* end class ExplorerDragSupport */