001: /*
002: * @(#)BasicTransferable.java 8/25/2006
003: *
004: * Copyright 2002 - 2006 JIDE Software Inc. All rights reserved.
005: */
006:
007: package com.jidesoft.utils;
008:
009: import javax.swing.plaf.UIResource;
010: import java.awt.datatransfer.DataFlavor;
011: import java.awt.datatransfer.Transferable;
012: import java.awt.datatransfer.UnsupportedFlavorException;
013: import java.io.*;
014:
015: /**
016: * A transferable implementation for the default data transfer of some Swing
017: * components.
018: * <p/>
019: * This is copy from the same class as JDK. The original class is pacakge local.
020: *
021: * @author Timothy Prinzing
022: * @version 1.9 12/19/03
023: */
024: public class BasicTransferable implements Transferable, UIResource {
025:
026: protected String plainData;
027: protected String htmlData;
028:
029: private static DataFlavor[] htmlFlavors;
030: private static DataFlavor[] stringFlavors;
031: private static DataFlavor[] plainFlavors;
032:
033: static {
034: try {
035: BasicTransferable.htmlFlavors = new DataFlavor[3];
036: BasicTransferable.htmlFlavors[0] = new DataFlavor(
037: "text/html;class=java.lang.String");
038: BasicTransferable.htmlFlavors[1] = new DataFlavor(
039: "text/html;class=java.io.Reader");
040: BasicTransferable.htmlFlavors[2] = new DataFlavor(
041: "text/html;charset=unicode;class=java.io.InputStream");
042:
043: BasicTransferable.plainFlavors = new DataFlavor[3];
044: BasicTransferable.plainFlavors[0] = new DataFlavor(
045: "text/plain;class=java.lang.String");
046: BasicTransferable.plainFlavors[1] = new DataFlavor(
047: "text/plain;class=java.io.Reader");
048: BasicTransferable.plainFlavors[2] = new DataFlavor(
049: "text/plain;charset=unicode;class=java.io.InputStream");
050:
051: BasicTransferable.stringFlavors = new DataFlavor[2];
052: BasicTransferable.stringFlavors[0] = new DataFlavor(
053: DataFlavor.javaJVMLocalObjectMimeType
054: + ";class=java.lang.String");
055: BasicTransferable.stringFlavors[1] = DataFlavor.stringFlavor;
056:
057: } catch (ClassNotFoundException cle) {
058: System.err.println("error initializing BasicTranserable");
059: }
060: }
061:
062: public BasicTransferable(String plainData, String htmlData) {
063: this .plainData = plainData;
064: this .htmlData = htmlData;
065: }
066:
067: /**
068: * Returns an array of DataFlavor objects indicating the flavors the data
069: * can be provided in. The array should be ordered according to preference
070: * for providing the data (from most richly descriptive to least descriptive).
071: *
072: * @return an array of data flavors in which this data can be transferred
073: */
074: public DataFlavor[] getTransferDataFlavors() {
075: DataFlavor[] richerFlavors = getRicherFlavors();
076: int nRicher = (richerFlavors != null) ? richerFlavors.length
077: : 0;
078: int nHTML = (isHTMLSupported()) ? BasicTransferable.htmlFlavors.length
079: : 0;
080: int nPlain = (isPlainSupported()) ? BasicTransferable.plainFlavors.length
081: : 0;
082: int nString = (isPlainSupported()) ? BasicTransferable.stringFlavors.length
083: : 0;
084: int nFlavors = nRicher + nHTML + nPlain + nString;
085: DataFlavor[] flavors = new DataFlavor[nFlavors];
086:
087: // fill in the array
088: int nDone = 0;
089: if (nRicher > 0) {
090: System.arraycopy(richerFlavors, 0, flavors, nDone, nRicher);
091: nDone += nRicher;
092: }
093: if (nHTML > 0) {
094: System.arraycopy(BasicTransferable.htmlFlavors, 0, flavors,
095: nDone, nHTML);
096: nDone += nHTML;
097: }
098: if (nPlain > 0) {
099: System.arraycopy(BasicTransferable.plainFlavors, 0,
100: flavors, nDone, nPlain);
101: nDone += nPlain;
102: }
103: if (nString > 0) {
104: System.arraycopy(BasicTransferable.stringFlavors, 0,
105: 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: *
115: * @param flavor the requested flavor for the data
116: * @return boolean indicating whether or not the data flavor is supported
117: */
118: public boolean isDataFlavorSupported(DataFlavor flavor) {
119: DataFlavor[] flavors = getTransferDataFlavors();
120: for (int i = 0; i < flavors.length; i++) {
121: if (flavors[i].equals(flavor)) {
122: return true;
123: }
124: }
125: return false;
126: }
127:
128: /**
129: * Returns an object which represents the data to be transferred. The class
130: * of the object returned is defined by the representation class of the flavor.
131: *
132: * @param flavor the requested flavor for the data
133: * @throws java.io.IOException if the data is no longer available
134: * in the requested flavor.
135: * @throws java.awt.datatransfer.UnsupportedFlavorException
136: * if the requested data flavor is
137: * not supported.
138: * @see java.awt.datatransfer.DataFlavor#getRepresentationClass
139: */
140: public Object getTransferData(DataFlavor flavor)
141: throws UnsupportedFlavorException, IOException {
142: DataFlavor[] richerFlavors = getRicherFlavors();
143: if (isRicherFlavor(flavor)) {
144: return getRicherData(flavor);
145: } else if (isHTMLFlavor(flavor)) {
146: String data = getHTMLData();
147: data = (data == null) ? "" : data;
148: if (String.class.equals(flavor.getRepresentationClass())) {
149: return data;
150: } else if (Reader.class.equals(flavor
151: .getRepresentationClass())) {
152: return new StringReader(data);
153: } else if (InputStream.class.equals(flavor
154: .getRepresentationClass())) {
155: return new StringBufferInputStream(data);
156: }
157: // fall through to unsupported
158: } else if (isPlainFlavor(flavor)) {
159: String data = getPlainData();
160: data = (data == null) ? "" : data;
161: if (String.class.equals(flavor.getRepresentationClass())) {
162: return data;
163: } else if (Reader.class.equals(flavor
164: .getRepresentationClass())) {
165: return new StringReader(data);
166: } else if (InputStream.class.equals(flavor
167: .getRepresentationClass())) {
168: return new StringBufferInputStream(data);
169: }
170: // fall through to unsupported
171:
172: } else if (isStringFlavor(flavor)) {
173: String data = getPlainData();
174: data = (data == null) ? "" : data;
175: return data;
176: }
177: throw new UnsupportedFlavorException(flavor);
178: }
179:
180: // --- richer subclass flavors ----------------------------------------------
181:
182: protected boolean isRicherFlavor(DataFlavor flavor) {
183: DataFlavor[] richerFlavors = getRicherFlavors();
184: int nFlavors = (richerFlavors != null) ? richerFlavors.length
185: : 0;
186: for (int i = 0; i < nFlavors; i++) {
187: if (richerFlavors[i].equals(flavor)) {
188: return true;
189: }
190: }
191: return false;
192: }
193:
194: /**
195: * Some subclasses will have flavors that are more descriptive than HTML
196: * or plain text. If this method returns a non-null value, it will be
197: * placed at the start of the array of supported flavors.
198: */
199: protected DataFlavor[] getRicherFlavors() {
200: return null;
201: }
202:
203: protected Object getRicherData(DataFlavor flavor)
204: 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: *
214: * @param flavor the requested flavor for the data
215: * @return boolean indicating whether or not the data flavor is supported
216: */
217: protected boolean isHTMLFlavor(DataFlavor flavor) {
218: DataFlavor[] flavors = BasicTransferable.htmlFlavors;
219: for (int i = 0; i < flavors.length; i++) {
220: if (flavors[i].equals(flavor)) {
221: return true;
222: }
223: }
224: return false;
225: }
226:
227: /**
228: * Should the HTML flavors be offered? If so, the method
229: * getHTMLData should be implemented to provide something reasonable.
230: */
231: protected boolean isHTMLSupported() {
232: return htmlData != null;
233: }
234:
235: /**
236: * Fetch the data in a text/html format
237: */
238: protected String getHTMLData() {
239: return htmlData;
240: }
241:
242: // --- plain text flavors ----------------------------------------------------
243:
244: /**
245: * Returns whether or not the specified data flavor is an plain flavor that
246: * is supported.
247: *
248: * @param flavor the requested flavor for the data
249: * @return boolean indicating whether or not the data flavor is supported
250: */
251: protected boolean isPlainFlavor(DataFlavor flavor) {
252: DataFlavor[] flavors = BasicTransferable.plainFlavors;
253: for (int i = 0; i < flavors.length; i++) {
254: if (flavors[i].equals(flavor)) {
255: return true;
256: }
257: }
258: return false;
259: }
260:
261: /**
262: * Should the plain text flavors be offered? If so, the method
263: * getPlainData should be implemented to provide something reasonable.
264: */
265: protected boolean isPlainSupported() {
266: return plainData != null;
267: }
268:
269: /**
270: * Fetch the data in a text/plain format.
271: */
272: protected String getPlainData() {
273: return plainData;
274: }
275:
276: // --- string flavorss --------------------------------------------------------
277:
278: /**
279: * Returns whether or not the specified data flavor is a String flavor that
280: * is supported.
281: *
282: * @param flavor the requested flavor for the data
283: * @return boolean indicating whether or not the data flavor is supported
284: */
285: protected boolean isStringFlavor(DataFlavor flavor) {
286: DataFlavor[] flavors = BasicTransferable.stringFlavors;
287: for (int i = 0; i < flavors.length; i++) {
288: if (flavors[i].equals(flavor)) {
289: return true;
290: }
291: }
292: return false;
293: }
294:
295: }
|