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-2007 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:
042: package org.netbeans.modules.visualweb.designer;
043:
044: import java.awt.datatransfer.DataFlavor;
045: import java.awt.datatransfer.Transferable;
046: import java.awt.dnd.DnDConstants;
047: import java.awt.dnd.DropTarget;
048: import java.awt.dnd.DropTargetDragEvent;
049: import java.awt.dnd.DropTargetDropEvent;
050: import java.awt.dnd.DropTargetEvent;
051: import java.awt.dnd.DropTargetListener;
052: import java.util.TooManyListenersException;
053: import javax.swing.JComponent;
054: import javax.swing.TransferHandler;
055: import javax.swing.event.EventListenerList;
056:
057: /**
058: * XXX #101880 In order to avoid rescheduling the drop. The default Swing impl, first
059: * processes the default listener (which handles the TransferHandler), and only
060: * after notifies the other listeners, which causes an issue when doing drop.
061: * We first need to notify the other listeners in order to provide the update
062: * of the drop position.
063: *
064: * XXX Be aware that in the other listeners one can't call accept/rejectDrag(Drop) otherwise it will breaks.
065: *
066: *
067: * @author Peter Zavadsky
068: */
069: public class DesignerPaneDropTarget extends DropTarget {
070:
071: private static final DropTargetListener DEFAULT_TRANSFER_HANDLER_DROP_TARGET_LISTENER = new DefaultTransferHandlerDropTargetListener();
072:
073: /** Hold the 'secondary' listeners. */
074: private EventListenerList listenerList;
075:
076: public DesignerPaneDropTarget(DesignerPane designerPane) {
077: super ();
078: setComponent(designerPane);
079: try {
080: super
081: .addDropTargetListener(DEFAULT_TRANSFER_HANDLER_DROP_TARGET_LISTENER);
082: } catch (TooManyListenersException tmle) {
083: // No op.
084: }
085: }
086:
087: public void addDropTargetListener(DropTargetListener dtl)
088: throws TooManyListenersException {
089: // Since the super class only supports one DropTargetListener,
090: // and we add one from the constructor, we always add to the
091: // extended list.
092: if (listenerList == null) {
093: listenerList = new EventListenerList();
094: }
095: listenerList.add(DropTargetListener.class, dtl);
096: }
097:
098: public void removeDropTargetListener(DropTargetListener dtl) {
099: if (listenerList != null) {
100: listenerList.remove(DropTargetListener.class, dtl);
101: }
102: }
103:
104: // --- DropTargetListener methods (multicast) --------------------------
105:
106: public void dragEnter(DropTargetDragEvent e) {
107: super .dragEnter(e);
108: if (listenerList != null) {
109: Object[] listeners = listenerList.getListenerList();
110: for (int i = listeners.length - 2; i >= 0; i -= 2) {
111: if (listeners[i] == DropTargetListener.class) {
112: ((DropTargetListener) listeners[i + 1])
113: .dragEnter(e);
114: }
115: }
116: }
117: }
118:
119: public void dragOver(DropTargetDragEvent e) {
120: super .dragOver(e);
121: if (listenerList != null) {
122: Object[] listeners = listenerList.getListenerList();
123: for (int i = listeners.length - 2; i >= 0; i -= 2) {
124: if (listeners[i] == DropTargetListener.class) {
125: ((DropTargetListener) listeners[i + 1]).dragOver(e);
126: }
127: }
128: }
129: }
130:
131: public void dragExit(DropTargetEvent e) {
132: super .dragExit(e);
133: if (listenerList != null) {
134: Object[] listeners = listenerList.getListenerList();
135: for (int i = listeners.length - 2; i >= 0; i -= 2) {
136: if (listeners[i] == DropTargetListener.class) {
137: ((DropTargetListener) listeners[i + 1]).dragExit(e);
138: }
139: }
140: }
141: }
142:
143: public void drop(DropTargetDropEvent e) {
144: // super.drop(e);
145: if (listenerList != null) {
146: Object[] listeners = listenerList.getListenerList();
147: for (int i = listeners.length - 2; i >= 0; i -= 2) {
148: if (listeners[i] == DropTargetListener.class) {
149: ((DropTargetListener) listeners[i + 1]).drop(e);
150: }
151: }
152: }
153: // XXX The default is proceeded after the other has a chance to update the position.
154: super .drop(e);
155: }
156:
157: public void dropActionChanged(DropTargetDragEvent e) {
158: super .dropActionChanged(e);
159: if (listenerList != null) {
160: Object[] listeners = listenerList.getListenerList();
161: for (int i = listeners.length - 2; i >= 0; i -= 2) {
162: if (listeners[i] == DropTargetListener.class) {
163: ((DropTargetListener) listeners[i + 1])
164: .dropActionChanged(e);
165: }
166: }
167: }
168: }
169:
170: // XXX Copied from TransferHandler.DropHandler
171: // XXX Does it need to be Serializable?
172: private static class DefaultTransferHandlerDropTargetListener
173: implements DropTargetListener /*, Serializable*/{
174:
175: private boolean canImport;
176:
177: private boolean actionSupported(int action) {
178: // return (action & (COPY_OR_MOVE | LINK)) != NONE;
179: return (action & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK)) != DnDConstants.ACTION_NONE;
180: }
181:
182: // --- DropTargetListener methods -----------------------------------
183:
184: public void dragEnter(DropTargetDragEvent e) {
185: DataFlavor[] flavors = e.getCurrentDataFlavors();
186:
187: JComponent c = (JComponent) e.getDropTargetContext()
188: .getComponent();
189: TransferHandler importer = c.getTransferHandler();
190:
191: // if (importer != null && importer.canImport(c, flavors)) {
192: // XXX #99457 Internally enhanced TransferHandler to use also Transferable to compare.
193: boolean canImporterImport;
194: if (importer instanceof DesignerTransferHandler) {
195: canImporterImport = ((DesignerTransferHandler) importer)
196: .canImport(c, flavors, e.getTransferable());
197: } else {
198: canImporterImport = importer == null ? false : importer
199: .canImport(c, flavors);
200: }
201: if (canImporterImport) {
202: canImport = true;
203: } else {
204: canImport = false;
205: }
206:
207: int dropAction = e.getDropAction();
208:
209: if (canImport && actionSupported(dropAction)) {
210: e.acceptDrag(dropAction);
211: } else {
212: e.rejectDrag();
213: }
214: }
215:
216: public void dragOver(DropTargetDragEvent e) {
217: int dropAction = e.getDropAction();
218:
219: if (canImport && actionSupported(dropAction)) {
220: e.acceptDrag(dropAction);
221: } else {
222: e.rejectDrag();
223: }
224: }
225:
226: public void dragExit(DropTargetEvent e) {
227: }
228:
229: public void drop(DropTargetDropEvent e) {
230: int dropAction = e.getDropAction();
231:
232: JComponent c = (JComponent) e.getDropTargetContext()
233: .getComponent();
234: TransferHandler importer = c.getTransferHandler();
235:
236: if (canImport && importer != null
237: && actionSupported(dropAction)) {
238: e.acceptDrop(dropAction);
239:
240: try {
241: Transferable t = e.getTransferable();
242: e.dropComplete(importer.importData(c, t));
243: } catch (RuntimeException re) {
244: e.dropComplete(false);
245: }
246: } else {
247: e.rejectDrop();
248: }
249: }
250:
251: public void dropActionChanged(DropTargetDragEvent e) {
252: int dropAction = e.getDropAction();
253:
254: if (canImport && actionSupported(dropAction)) {
255: e.acceptDrag(dropAction);
256: } else {
257: e.rejectDrag();
258: }
259: }
260: }
261: }
|