1 /* 2 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.embed.swing; 27 28 import com.sun.javafx.embed.EmbeddedSceneDSInterface; 29 import com.sun.javafx.tk.Toolkit; 30 import java.awt.datatransfer.DataFlavor; 31 import java.awt.datatransfer.Transferable; 32 import java.awt.dnd.DropTargetDragEvent; 33 import java.awt.dnd.DropTargetDropEvent; 34 import java.util.Arrays; 35 import java.util.Collections; 36 import java.util.Map; 37 import java.util.Set; 38 import javafx.scene.input.TransferMode; 39 40 /** 41 * Drag source to deliver data from Swing environment to embedded FX scene. 42 */ 43 final class SwingDragSource implements EmbeddedSceneDSInterface { 44 45 private int sourceActions; 46 private Map<String, Object> mimeType2Data = Collections.EMPTY_MAP; 47 48 SwingDragSource() { 49 } 50 51 void updateContents(final DropTargetDragEvent e, boolean fetchData) { 52 sourceActions = e.getSourceActions(); 53 updateData(e.getTransferable(), fetchData); 54 } 55 56 void updateContents(final DropTargetDropEvent e, boolean fetchData) { 57 sourceActions = e.getSourceActions(); 58 updateData(e.getTransferable(), fetchData); 59 } 60 61 private void updateData(Transferable t, boolean fetchData) { 62 final Map<String, DataFlavor> mimeType2DataFlavor = 63 DataFlavorUtils.adjustSwingDataFlavors( 64 t.getTransferDataFlavors()); 65 66 // If we keep reference to source Transferable in SwingDragSource and 67 // call Transferable#getTransferData() on it from 68 // SwingDragSource#getData() we may run into 69 // "java.awt.dnd.InvalidDnDOperationException" issue as 70 // SwingDragSource#getData() is called from FX user code and from 71 // QuantumClipboard#getContent() (sik!). These calls usually take 72 // place in the context of 73 // EmbeddedSceneDTInterface#handleDragDrop() method as the 74 // normal handling of DnD. 75 // Instead of keeping reference to source Transferable we just read 76 // all its data while in the context safe for calling 77 // Transferable#getTransferData(). 78 // 79 // This observation is true for standard AWT Transferable-s. 80 // Things may be totally broken for custom Transferable-s though. 81 82 // For performance reasons, the DRAG_ENTERED and DRAG_OVER event 83 // handlers pass fetchData == false so as to update the set of 84 // available MIME types only. The DRAG_DROPPED handler passes 85 // fetchData == true which also fetches all the data. 86 // NOTE: Due to JDK-8028585 this code won't be able to fetch data 87 // when invoked from handlers other than DROPPED in any case. 88 89 try { 90 mimeType2Data = DataFlavorUtils.readAllData(t, mimeType2DataFlavor, 91 fetchData); 92 } catch (Exception e) { 93 mimeType2Data = Collections.EMPTY_MAP; 94 } 95 } 96 97 @Override 98 public Set<TransferMode> getSupportedActions() { 99 assert Toolkit.getToolkit().isFxUserThread(); 100 return SwingDnD.dropActionsToTransferModes(sourceActions); 101 } 102 103 @Override 104 public Object getData(final String mimeType) { 105 assert Toolkit.getToolkit().isFxUserThread(); 106 return mimeType2Data.get(mimeType); 107 } 108 109 @Override 110 public String[] getMimeTypes() { 111 assert Toolkit.getToolkit().isFxUserThread(); 112 return mimeType2Data.keySet().toArray(new String[0]); 113 } 114 115 @Override 116 public boolean isMimeTypeAvailable(final String mimeType) { 117 assert Toolkit.getToolkit().isFxUserThread(); 118 return Arrays.asList(getMimeTypes()).contains(mimeType); 119 } 120 121 @Override 122 public void dragDropEnd(TransferMode performedAction) { 123 throw new UnsupportedOperationException(); 124 } 125 }