001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.openide.explorer.view;
042:
043: import org.openide.nodes.Node;
044:
045: import java.awt.Dialog;
046: import java.awt.datatransfer.Transferable;
047: import java.awt.dnd.*;
048:
049: import java.io.IOException;
050:
051: import java.util.TooManyListenersException;
052: import java.util.logging.Level;
053: import java.util.logging.Logger;
054:
055: import javax.swing.JComponent;
056: import javax.swing.SwingUtilities;
057: import org.openide.util.Exceptions;
058:
059: /** Support for the drag operations in explorer.
060: *
061: * @author Jiri Rechtacek
062: */
063: abstract class ExplorerDragSupport implements DragSourceListener,
064: DragGestureListener {
065: // Attributes
066:
067: /** True when we are active, false otherwise */
068: boolean active = false;
069:
070: /** Recognizes default gesture */
071: DragGestureRecognizer defaultGesture;
072:
073: /** The component which we are supporting (our client) */
074: protected JComponent comp;
075: ExplorerDnDManager exDnD = ExplorerDnDManager.getDefault();
076:
077: abstract int getAllowedDropActions();
078:
079: /** Initiating the drag */
080: public void dragGestureRecognized(DragGestureEvent dge) {
081: // 1. get seleced dragged nodes
082: Node[] nodes = obtainNodes(dge);
083:
084: // check nodes
085: if ((nodes == null) || (nodes.length == 0)) {
086: return;
087: }
088:
089: // 2. detect highest common action
090: int possibleNodeAction = getAllowedDragActions();
091:
092: for (int i = 0; i < nodes.length; i++) {
093: if ((possibleNodeAction & DnDConstants.ACTION_MOVE) != 0) {
094: if (!nodes[i].canCut()) {
095: possibleNodeAction = DnDConstants.ACTION_COPY
096: | DnDConstants.ACTION_REFERENCE;
097: }
098: }
099:
100: if ((possibleNodeAction & DnDConstants.ACTION_COPY) != 0) {
101: if (!nodes[i].canCopy()) {
102: possibleNodeAction = DnDConstants.ACTION_NONE;
103: }
104: }
105: }
106:
107: exDnD = ExplorerDnDManager.getDefault();
108: exDnD.setNodeAllowedActions(possibleNodeAction);
109:
110: int dragAction = dge.getDragAction();
111:
112: boolean dragStatus = canDrag(dragAction, possibleNodeAction);
113:
114: // 3. get transferable and start the drag
115: try {
116: // for MOVE
117: Transferable transferable;
118:
119: if ((possibleNodeAction & DnDConstants.ACTION_MOVE) != 0) {
120: // for MOVE
121: transferable = DragDropUtilities.getNodeTransferable(
122: nodes, DnDConstants.ACTION_MOVE);
123: exDnD.setDraggedTransferable(transferable, true);
124:
125: // for COPY too
126: transferable = DragDropUtilities.getNodeTransferable(
127: nodes, DnDConstants.ACTION_COPY);
128: exDnD.setDraggedTransferable(transferable, false);
129: } else if ((possibleNodeAction & DnDConstants.ACTION_COPY) != 0) {
130: // for COPY
131: transferable = DragDropUtilities.getNodeTransferable(
132: nodes, DnDConstants.ACTION_COPY);
133: exDnD.setDraggedTransferable(transferable, false);
134: } else {
135: // transferable for NONE
136: transferable = Node.EMPTY.drag();
137: exDnD.setDraggedTransferable(transferable, false);
138: }
139:
140: exDnD.setDraggedNodes(nodes);
141:
142: Dialog d = (Dialog) SwingUtilities.getAncestorOfClass(
143: Dialog.class, comp);
144:
145: if ((d != null) && d.isModal()) {
146: exDnD.setDnDActive(false);
147:
148: return;
149: } else {
150: exDnD.setDnDActive(true);
151: dge.startDrag(null, transferable, this );
152: }
153: } catch (InvalidDnDOperationException exc) {
154: // cannot start the drag, notify as informational
155: Logger.getLogger(ExplorerDragSupport.class.getName()).log(
156: Level.WARNING, null, exc);
157: exDnD.setDnDActive(false);
158: } catch (IOException exc) {
159: // cannot start the drag, notify user
160: Exceptions.printStackTrace(exc);
161: exDnD.setDnDActive(false);
162: }
163: }
164:
165: protected int getAllowedDragActions() {
166: return DnDConstants.ACTION_NONE;
167: }
168:
169: private boolean canDrag(int targetAction, int possibleAction) {
170: return (possibleAction & targetAction) != 0;
171: }
172:
173: public void dragEnter(DragSourceDragEvent dsde) {
174: doDragOver(dsde);
175: }
176:
177: public void dragOver(DragSourceDragEvent dsde) {
178: doDragOver(dsde);
179: }
180:
181: public void dropActionChanged(DragSourceDragEvent dsde) {
182: }
183:
184: public void dragExit(DragSourceEvent dse) {
185: }
186:
187: private void doDragOver(DragSourceDragEvent dsde) {
188: }
189:
190: public void dragDropEnd(DragSourceDropEvent dsde) {
191: // not transferable for MOVE nor COPY
192: exDnD.setDraggedTransferable(null, true);
193: exDnD.setDraggedTransferable(null, false);
194:
195: // no nodes are dragged
196: exDnD.setDraggedNodes(null);
197:
198: // no drop candidate
199: NodeRenderer.dragExit();
200:
201: // no more active
202: exDnD.setDnDActive(false);
203: }
204:
205: /** Activates or deactivates Drag support on asociated JTree
206: * component
207: * @param active true if the support should be active, false
208: * otherwise
209: */
210: public void activate(boolean active) {
211: if (this .active == active) {
212: return;
213: }
214:
215: this .active = active;
216:
217: DragGestureRecognizer dgr = getDefaultGestureRecognizer();
218:
219: if (active) {
220: dgr.setSourceActions(getAllowedDragActions());
221:
222: try {
223: dgr.removeDragGestureListener(this );
224: dgr.addDragGestureListener(this );
225: } catch (TooManyListenersException exc) {
226: throw new IllegalStateException(
227: "Too many listeners for drag gesture."); // NOI18N
228: }
229: } else {
230: dgr.removeDragGestureListener(this );
231: }
232: }
233:
234: /** Safe getter for default gesture<br>
235: * (creates the gesture when called for the first time)
236: */
237: DragGestureRecognizer getDefaultGestureRecognizer() {
238: if (defaultGesture == null) {
239: DragSource ds = DragSource.getDefaultDragSource();
240: defaultGesture = ds.createDefaultDragGestureRecognizer(
241: comp, getAllowedDragActions(), this );
242: }
243:
244: return defaultGesture;
245: }
246:
247: /** Utility method. Returns either selected nodes in tree
248: * (if cursor hotspot is above some selected node) or the node
249: * the cursor points to.
250: * @return Node array or null if position of the cursor points
251: * to no node.
252: */
253: abstract Node[] obtainNodes(DragGestureEvent dge);
254: }
255: /* end class ExplorerDragSupport */
|