1/* 2 * Copyright (c) 2000, 2002, 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 */ 25package javax.swing.plaf.basic; 26 27import sun.datatransfer.DataFlavorUtil; 28 29import java.io.*; 30import java.awt.datatransfer.*; 31import javax.swing.plaf.UIResource; 32 33/** 34 * A transferable implementation for the default data transfer of some Swing 35 * components. 36 * 37 * @author Timothy Prinzing 38 */ 39class BasicTransferable implements Transferable, UIResource { 40 41 protected String plainData; 42 protected String htmlData; 43 44 private static DataFlavor[] htmlFlavors; 45 private static DataFlavor[] stringFlavors; 46 private static DataFlavor[] plainFlavors; 47 48 static { 49 try { 50 htmlFlavors = new DataFlavor[3]; 51 htmlFlavors[0] = new DataFlavor("text/html;class=java.lang.String"); 52 htmlFlavors[1] = new DataFlavor("text/html;class=java.io.Reader"); 53 htmlFlavors[2] = new DataFlavor("text/html;charset=unicode;class=java.io.InputStream"); 54 55 plainFlavors = new DataFlavor[3]; 56 plainFlavors[0] = new DataFlavor("text/plain;class=java.lang.String"); 57 plainFlavors[1] = new DataFlavor("text/plain;class=java.io.Reader"); 58 plainFlavors[2] = new DataFlavor("text/plain;charset=unicode;class=java.io.InputStream"); 59 60 stringFlavors = new DataFlavor[2]; 61 stringFlavors[0] = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType+";class=java.lang.String"); 62 stringFlavors[1] = DataFlavor.stringFlavor; 63 64 } catch (ClassNotFoundException cle) { 65 System.err.println("error initializing javax.swing.plaf.basic.BasicTranserable"); 66 } 67 } 68 69 public BasicTransferable(String plainData, String htmlData) { 70 this.plainData = plainData; 71 this.htmlData = htmlData; 72 } 73 74 75 /** 76 * Returns an array of DataFlavor objects indicating the flavors the data 77 * can be provided in. The array should be ordered according to preference 78 * for providing the data (from most richly descriptive to least descriptive). 79 * @return an array of data flavors in which this data can be transferred 80 */ 81 public DataFlavor[] getTransferDataFlavors() { 82 DataFlavor[] richerFlavors = getRicherFlavors(); 83 int nRicher = (richerFlavors != null) ? richerFlavors.length : 0; 84 int nHTML = (isHTMLSupported()) ? htmlFlavors.length : 0; 85 int nPlain = (isPlainSupported()) ? plainFlavors.length: 0; 86 int nString = (isPlainSupported()) ? stringFlavors.length : 0; 87 int nFlavors = nRicher + nHTML + nPlain + nString; 88 DataFlavor[] flavors = new DataFlavor[nFlavors]; 89 90 // fill in the array 91 int nDone = 0; 92 if (nRicher > 0) { 93 System.arraycopy(richerFlavors, 0, flavors, nDone, nRicher); 94 nDone += nRicher; 95 } 96 if (nHTML > 0) { 97 System.arraycopy(htmlFlavors, 0, flavors, nDone, nHTML); 98 nDone += nHTML; 99 } 100 if (nPlain > 0) { 101 System.arraycopy(plainFlavors, 0, flavors, nDone, nPlain); 102 nDone += nPlain; 103 } 104 if (nString > 0) { 105 System.arraycopy(stringFlavors, 0, flavors, nDone, nString); 106 nDone += nString; 107 } 108 return flavors; 109 } 110 111 /** 112 * Returns whether or not the specified data flavor is supported for 113 * this object. 114 * @param flavor the requested flavor for the data 115 * @return boolean indicating whether or not the data flavor is supported 116 */ 117 public boolean isDataFlavorSupported(DataFlavor flavor) { 118 DataFlavor[] flavors = getTransferDataFlavors(); 119 for (int i = 0; i < flavors.length; i++) { 120 if (flavors[i].equals(flavor)) { 121 return true; 122 } 123 } 124 return false; 125 } 126 127 /** 128 * Returns an object which represents the data to be transferred. The class 129 * of the object returned is defined by the representation class of the flavor. 130 * 131 * @param flavor the requested flavor for the data 132 * @see DataFlavor#getRepresentationClass 133 * @exception IOException if the data is no longer available 134 * in the requested flavor. 135 * @exception UnsupportedFlavorException if the requested data flavor is 136 * not supported. 137 */ 138 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { 139 DataFlavor[] richerFlavors = getRicherFlavors(); 140 if (isRicherFlavor(flavor)) { 141 return getRicherData(flavor); 142 } else if (isHTMLFlavor(flavor)) { 143 String data = getHTMLData(); 144 data = (data == null) ? "" : data; 145 if (String.class.equals(flavor.getRepresentationClass())) { 146 return data; 147 } else if (Reader.class.equals(flavor.getRepresentationClass())) { 148 return new StringReader(data); 149 } else if (InputStream.class.equals(flavor.getRepresentationClass())) { 150 return createInputStream(flavor, data); 151 } 152 // fall through to unsupported 153 } else if (isPlainFlavor(flavor)) { 154 String data = getPlainData(); 155 data = (data == null) ? "" : data; 156 if (String.class.equals(flavor.getRepresentationClass())) { 157 return data; 158 } else if (Reader.class.equals(flavor.getRepresentationClass())) { 159 return new StringReader(data); 160 } else if (InputStream.class.equals(flavor.getRepresentationClass())) { 161 return createInputStream(flavor, data); 162 } 163 // fall through to unsupported 164 165 } else if (isStringFlavor(flavor)) { 166 String data = getPlainData(); 167 data = (data == null) ? "" : data; 168 return data; 169 } 170 throw new UnsupportedFlavorException(flavor); 171 } 172 173 private InputStream createInputStream(DataFlavor flavor, String data) 174 throws IOException, UnsupportedFlavorException { 175 String cs = DataFlavorUtil.getTextCharset(flavor); 176 if (cs == null) { 177 throw new UnsupportedFlavorException(flavor); 178 } 179 return new ByteArrayInputStream(data.getBytes(cs)); 180 } 181 182 // --- richer subclass flavors ---------------------------------------------- 183 184 protected boolean isRicherFlavor(DataFlavor flavor) { 185 DataFlavor[] richerFlavors = getRicherFlavors(); 186 int nFlavors = (richerFlavors != null) ? richerFlavors.length : 0; 187 for (int i = 0; i < nFlavors; i++) { 188 if (richerFlavors[i].equals(flavor)) { 189 return true; 190 } 191 } 192 return false; 193 } 194 195 /** 196 * Some subclasses will have flavors that are more descriptive than HTML 197 * or plain text. If this method returns a non-null value, it will be 198 * placed at the start of the array of supported flavors. 199 */ 200 protected DataFlavor[] getRicherFlavors() { 201 return null; 202 } 203 204 protected Object getRicherData(DataFlavor flavor) throws UnsupportedFlavorException { 205 return null; 206 } 207 208 // --- html flavors ---------------------------------------------------------- 209 210 /** 211 * Returns whether or not the specified data flavor is an HTML flavor that 212 * is supported. 213 * @param flavor the requested flavor for the data 214 * @return boolean indicating whether or not the data flavor is supported 215 */ 216 protected boolean isHTMLFlavor(DataFlavor flavor) { 217 DataFlavor[] flavors = htmlFlavors; 218 for (int i = 0; i < flavors.length; i++) { 219 if (flavors[i].equals(flavor)) { 220 return true; 221 } 222 } 223 return false; 224 } 225 226 /** 227 * Should the HTML flavors be offered? If so, the method 228 * getHTMLData should be implemented to provide something reasonable. 229 */ 230 protected boolean isHTMLSupported() { 231 return htmlData != null; 232 } 233 234 /** 235 * Fetch the data in a text/html format 236 */ 237 protected String getHTMLData() { 238 return htmlData; 239 } 240 241 // --- plain text flavors ---------------------------------------------------- 242 243 /** 244 * Returns whether or not the specified data flavor is an plain flavor that 245 * is supported. 246 * @param flavor the requested flavor for the data 247 * @return boolean indicating whether or not the data flavor is supported 248 */ 249 protected boolean isPlainFlavor(DataFlavor flavor) { 250 DataFlavor[] flavors = plainFlavors; 251 for (int i = 0; i < flavors.length; i++) { 252 if (flavors[i].equals(flavor)) { 253 return true; 254 } 255 } 256 return false; 257 } 258 259 /** 260 * Should the plain text flavors be offered? If so, the method 261 * getPlainData should be implemented to provide something reasonable. 262 */ 263 protected boolean isPlainSupported() { 264 return plainData != null; 265 } 266 267 /** 268 * Fetch the data in a text/plain format. 269 */ 270 protected String getPlainData() { 271 return plainData; 272 } 273 274 // --- string flavorss -------------------------------------------------------- 275 276 /** 277 * Returns whether or not the specified data flavor is a String flavor that 278 * is supported. 279 * @param flavor the requested flavor for the data 280 * @return boolean indicating whether or not the data flavor is supported 281 */ 282 protected boolean isStringFlavor(DataFlavor flavor) { 283 DataFlavor[] flavors = stringFlavors; 284 for (int i = 0; i < flavors.length; i++) { 285 if (flavors[i].equals(flavor)) { 286 return true; 287 } 288 } 289 return false; 290 } 291 292 293} 294