1 /* 2 * Copyright (c) 2000, 2013, 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.scene.input; 27 28 import java.util.Arrays; 29 import java.util.Collections; 30 import java.util.HashSet; 31 import java.util.Iterator; 32 import java.util.Set; 33 34 import com.sun.javafx.util.WeakReferenceQueue; 35 import javafx.beans.NamedArg; 36 37 /** 38 * Data format identifier used as means 39 * of identifying the data stored on a clipboard/dragboard. 40 * @since JavaFX 2.0 41 */ 42 public class DataFormat { 43 44 /** 45 * A static cache of all DataFormats created and currently in use. This is needed 46 * by the underlying implementation, such that, given a mime type, we can determine 47 * the associated DataFormat. The OS level is going to supply us with a mime type 48 * (or other string based key), and we need to be able to map this back to the FX 49 * DataFormat. 50 */ 51 private static final WeakReferenceQueue<DataFormat> DATA_FORMAT_LIST = new WeakReferenceQueue<DataFormat>(); 52 53 /** 54 * Represents a plain text string. 55 */ 56 public static final DataFormat PLAIN_TEXT = new DataFormat("text/plain"); 57 58 /** 59 * Represents an HTML formatted string. 60 */ 61 public static final DataFormat HTML = new DataFormat("text/html"); 62 63 /** 64 * Represents an RTF formatted string 65 */ 66 public static final DataFormat RTF = new DataFormat("text/rtf"); 67 68 /** 69 * Represents a URL, encoded as a String 70 */ 71 public static final DataFormat URL = new DataFormat("text/uri-list"); 72 73 /** 74 * A special platform specific image type, such as is commonly used 75 * on the clipboard and interoperates widely with other applications. 76 * For example, on Mac this might ultimately be a TIFF while on 77 * Windows it might be a DIB (device independent bitmap). 78 */ 79 public static final DataFormat IMAGE = new DataFormat("application/x-java-rawimage"); 80 81 /** 82 * Represents a List of Files. 83 */ 84 public static final DataFormat FILES = new DataFormat("application/x-java-file-list", "java.file-list"); 85 86 /** 87 * Data format used internally, represents dragged image. Making this 88 * a private field prevents user from creating this DataFormat and breaking 89 * our drag view implementation. 90 */ 91 private static final DataFormat DRAG_IMAGE = new DataFormat("application/x-java-drag-image"); 92 93 /** 94 * Data format used internally, represents offset in the dragged image. 95 * Making this a private field prevents user from creating this DataFormat 96 * and breaking our drag view implementation. 97 */ 98 private static final DataFormat DRAG_IMAGE_OFFSET = new DataFormat("application/x-java-drag-image-offset"); 99 100 /** 101 * A set of identifiers, typically mime types, for this DataFormat. 102 * In most cases this will be a single String. 103 */ 104 private final Set<String> identifier; 105 106 /** 107 * Create a new DataFormat, specifying the set of ids that are associated with 108 * this data format. Typically the ids are one or more mime types. For each 109 * id, any data associated with this DataFormat will be registered on the 110 * clipboard. For example, suppose I had the following: 111 * <pre><code> 112 * DataFormat fmt = new DataFormat("text/foo", "text/bar"); 113 * Clipboard clipboard = Clipboard.getSystemClipboard(); 114 * ClipboardContent content = new ClipboardContent(); 115 * content.put(fmt, "Hello"); 116 * clipboard.setContent(content); 117 * </code></pre> 118 * 119 * With the above code, if I were to look on the clipboard, I'd find the String "Hello" 120 * listed both for "text/foo" and "text/bar" on the clipboard. 121 * 122 * <p> 123 * Note that the ids may be subject to platform restrictions in some cases. 124 * For instance, Swing requires a mime type so if an {@code id} is not 125 * of the "type/subtype" format it won't be possible 126 * to drag data of this type from/to {@link javafx.embed.swing.JFXPanel}. 127 * </p> 128 * @param ids The set of ids used to represent this DataFormat on the clipboard. 129 * @throws IllegalArgumentException if one of the given mime types is already 130 * assigned to another DataFormat. 131 */ 132 public DataFormat(@NamedArg("ids") String... ids) { 133 DATA_FORMAT_LIST.cleanup(); 134 if (ids != null) { 135 for (String id : ids) { 136 if (lookupMimeType(id) != null) { 137 throw new IllegalArgumentException("DataFormat '" + id + 138 "' already exists."); 139 } 140 } 141 this.identifier = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(ids))); 142 } else { 143 this.identifier = Collections.<String>emptySet(); 144 } 145 146 // Add to the statis data format list. 147 DATA_FORMAT_LIST.add(this); 148 } 149 150 /** 151 * Gets the unmodifiable set of identifiers for this DataFormat. 152 * @return an unmodifiable set that is never null. 153 */ 154 public final Set<String> getIdentifiers() { 155 return identifier; 156 } 157 158 /** 159 * Returns a string representation of this {@code DataFormat} object. 160 * @return a string representation of this {@code DataFormat} object. 161 */ 162 @Override public String toString() { 163 if (identifier.isEmpty()) { 164 return "[]"; 165 } else if (identifier.size() == 1) { 166 StringBuilder sb = new StringBuilder("["); 167 sb.append(identifier.iterator().next()); 168 return (sb.append("]").toString()); 169 } else { 170 StringBuilder b = new StringBuilder("["); 171 Iterator<String> itr = identifier.iterator(); 172 while (itr.hasNext()) { 173 b = b.append(itr.next()); 174 if (itr.hasNext()) { 175 b = b.append(", "); 176 } 177 } 178 b = b.append("]"); 179 return b.toString(); 180 } 181 } 182 183 /** 184 * Returns a hash code for this {@code DataFormat} object. 185 * @return a hash code for this {@code DataFormat} object. 186 */ 187 @Override public int hashCode() { 188 int hash = 7; 189 190 for (String id : identifier) { 191 hash = 31 * hash + id.hashCode(); 192 } 193 194 return hash; 195 } 196 197 /** 198 * Indicates whether some other object is "equal to" this one. 199 * @param obj the reference object with which to compare. 200 * @return {@code true} if this object is equal to the {@code obj} argument; {@code false} otherwise. 201 */ 202 @Override public boolean equals(Object obj) { 203 if (obj == null || ! (obj instanceof DataFormat)) { 204 return false; 205 } 206 207 DataFormat otherDataFormat = (DataFormat) obj; 208 209 if (identifier.equals(otherDataFormat.identifier)) { 210 return true; 211 } 212 213 return false; 214 } 215 216 /** 217 * Looks for the DataFormat which has been previously created with 218 * the given mime type as one of its ids. 219 * @param mimeType If null or the empty string, then null is returned. 220 * @return The matching DataFormat 221 */ 222 public static DataFormat lookupMimeType(String mimeType) { 223 if (mimeType == null || mimeType.length() == 0) { 224 return null; 225 } 226 227 Iterator itr = DATA_FORMAT_LIST.iterator(); 228 while (itr.hasNext()) { 229 DataFormat dataFormat = (DataFormat) itr.next(); 230 if (dataFormat.getIdentifiers().contains(mimeType)) { 231 return dataFormat; 232 } 233 } 234 return null; 235 } 236 }