1. /*
  2. * @(#)SynthTransferable.java 1.2 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.gtk;
  8. import java.io.*;
  9. import java.awt.datatransfer.*;
  10. import javax.swing.plaf.UIResource;
  11. /**
  12. * A transferable implementation for the default data transfer of some Swing
  13. * components.
  14. *
  15. * @author Shannon Hickey
  16. * @version 1.2 01/23/03 (based on revision 1.7 of BasicTransferable)
  17. */
  18. class SynthTransferable implements Transferable, UIResource {
  19. protected String plainData;
  20. protected String htmlData;
  21. private static DataFlavor[] htmlFlavors;
  22. private static DataFlavor[] stringFlavors;
  23. private static DataFlavor[] plainFlavors;
  24. static {
  25. try {
  26. htmlFlavors = new DataFlavor[3];
  27. htmlFlavors[0] = new DataFlavor("text/html;class=java.lang.String");
  28. htmlFlavors[1] = new DataFlavor("text/html;class=java.io.Reader");
  29. htmlFlavors[2] = new DataFlavor("text/html;charset=unicode;class=java.io.InputStream");
  30. plainFlavors = new DataFlavor[3];
  31. plainFlavors[0] = new DataFlavor("text/plain;class=java.lang.String");
  32. plainFlavors[1] = new DataFlavor("text/plain;class=java.io.Reader");
  33. plainFlavors[2] = new DataFlavor("text/plain;charset=unicode;class=java.io.InputStream");
  34. stringFlavors = new DataFlavor[2];
  35. stringFlavors[0] = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType+";class=java.lang.String");
  36. stringFlavors[1] = DataFlavor.stringFlavor;
  37. } catch (ClassNotFoundException cle) {
  38. System.err.println("error initializing javax.swing.plaf.basic.BasicTranserable");
  39. }
  40. }
  41. public SynthTransferable(String plainData, String htmlData) {
  42. this.plainData = plainData;
  43. this.htmlData = htmlData;
  44. }
  45. /**
  46. * Returns an array of DataFlavor objects indicating the flavors the data
  47. * can be provided in. The array should be ordered according to preference
  48. * for providing the data (from most richly descriptive to least descriptive).
  49. * @return an array of data flavors in which this data can be transferred
  50. */
  51. public DataFlavor[] getTransferDataFlavors() {
  52. DataFlavor[] richerFlavors = getRicherFlavors();
  53. int nRicher = (richerFlavors != null) ? richerFlavors.length : 0;
  54. int nHTML = (isHTMLSupported()) ? htmlFlavors.length : 0;
  55. int nPlain = (isPlainSupported()) ? plainFlavors.length: 0;
  56. int nString = (isPlainSupported()) ? stringFlavors.length : 0;
  57. int nFlavors = nRicher + nHTML + nPlain + nString;
  58. DataFlavor[] flavors = new DataFlavor[nFlavors];
  59. // fill in the array
  60. int nDone = 0;
  61. if (nRicher > 0) {
  62. System.arraycopy(richerFlavors, 0, flavors, nDone, nRicher);
  63. nDone += nRicher;
  64. }
  65. if (nHTML > 0) {
  66. System.arraycopy(htmlFlavors, 0, flavors, nDone, nHTML);
  67. nDone += nHTML;
  68. }
  69. if (nPlain > 0) {
  70. System.arraycopy(plainFlavors, 0, flavors, nDone, nPlain);
  71. nDone += nPlain;
  72. }
  73. if (nString > 0) {
  74. System.arraycopy(stringFlavors, 0, flavors, nDone, nString);
  75. nDone += nString;
  76. }
  77. return flavors;
  78. }
  79. /**
  80. * Returns whether or not the specified data flavor is supported for
  81. * this object.
  82. * @param flavor the requested flavor for the data
  83. * @return boolean indicating whether or not the data flavor is supported
  84. */
  85. public boolean isDataFlavorSupported(DataFlavor flavor) {
  86. DataFlavor[] flavors = getTransferDataFlavors();
  87. for (int i = 0; i < flavors.length; i++) {
  88. if (flavors[i].equals(flavor)) {
  89. return true;
  90. }
  91. }
  92. return false;
  93. }
  94. /**
  95. * Returns an object which represents the data to be transferred. The class
  96. * of the object returned is defined by the representation class of the flavor.
  97. *
  98. * @param flavor the requested flavor for the data
  99. * @see DataFlavor#getRepresentationClass
  100. * @exception IOException if the data is no longer available
  101. * in the requested flavor.
  102. * @exception UnsupportedFlavorException if the requested data flavor is
  103. * not supported.
  104. */
  105. public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
  106. DataFlavor[] richerFlavors = getRicherFlavors();
  107. if (isRicherFlavor(flavor)) {
  108. return getRicherData(flavor);
  109. } else if (isHTMLFlavor(flavor)) {
  110. String data = getHTMLData();
  111. data = (data == null) ? "" : data;
  112. if (String.class.equals(flavor.getRepresentationClass())) {
  113. return data;
  114. } else if (Reader.class.equals(flavor.getRepresentationClass())) {
  115. return new StringReader(data);
  116. } else if (InputStream.class.equals(flavor.getRepresentationClass())) {
  117. return new StringBufferInputStream(data);
  118. }
  119. // fall through to unsupported
  120. } else if (isPlainFlavor(flavor)) {
  121. String data = getPlainData();
  122. data = (data == null) ? "" : data;
  123. if (String.class.equals(flavor.getRepresentationClass())) {
  124. return data;
  125. } else if (Reader.class.equals(flavor.getRepresentationClass())) {
  126. return new StringReader(data);
  127. } else if (InputStream.class.equals(flavor.getRepresentationClass())) {
  128. return new StringBufferInputStream(data);
  129. }
  130. // fall through to unsupported
  131. } else if (isStringFlavor(flavor)) {
  132. String data = getPlainData();
  133. data = (data == null) ? "" : data;
  134. return data;
  135. }
  136. throw new UnsupportedFlavorException(flavor);
  137. }
  138. // --- richer subclass flavors ----------------------------------------------
  139. protected boolean isRicherFlavor(DataFlavor flavor) {
  140. DataFlavor[] richerFlavors = getRicherFlavors();
  141. int nFlavors = (richerFlavors != null) ? richerFlavors.length : 0;
  142. for (int i = 0; i < nFlavors; i++) {
  143. if (richerFlavors[i].equals(flavor)) {
  144. return true;
  145. }
  146. }
  147. return false;
  148. }
  149. /**
  150. * Some subclasses will have flavors that are more descriptive than HTML
  151. * or plain text. If this method returns a non-null value, it will be
  152. * placed at the start of the array of supported flavors.
  153. */
  154. protected DataFlavor[] getRicherFlavors() {
  155. return null;
  156. }
  157. protected Object getRicherData(DataFlavor flavor) throws UnsupportedFlavorException {
  158. return null;
  159. }
  160. // --- html flavors ----------------------------------------------------------
  161. /**
  162. * Returns whether or not the specified data flavor is an HTML flavor that
  163. * is supported.
  164. * @param flavor the requested flavor for the data
  165. * @return boolean indicating whether or not the data flavor is supported
  166. */
  167. protected boolean isHTMLFlavor(DataFlavor flavor) {
  168. DataFlavor[] flavors = htmlFlavors;
  169. for (int i = 0; i < flavors.length; i++) {
  170. if (flavors[i].equals(flavor)) {
  171. return true;
  172. }
  173. }
  174. return false;
  175. }
  176. /**
  177. * Should the HTML flavors be offered? If so, the method
  178. * getHTMLData should be implemented to provide something reasonable.
  179. */
  180. protected boolean isHTMLSupported() {
  181. return htmlData != null;
  182. }
  183. /**
  184. * Fetch the data in a text/html format
  185. */
  186. protected String getHTMLData() {
  187. return htmlData;
  188. }
  189. // --- plain text flavors ----------------------------------------------------
  190. /**
  191. * Returns whether or not the specified data flavor is an plain flavor that
  192. * is supported.
  193. * @param flavor the requested flavor for the data
  194. * @return boolean indicating whether or not the data flavor is supported
  195. */
  196. protected boolean isPlainFlavor(DataFlavor flavor) {
  197. DataFlavor[] flavors = plainFlavors;
  198. for (int i = 0; i < flavors.length; i++) {
  199. if (flavors[i].equals(flavor)) {
  200. return true;
  201. }
  202. }
  203. return false;
  204. }
  205. /**
  206. * Should the plain text flavors be offered? If so, the method
  207. * getPlainData should be implemented to provide something reasonable.
  208. */
  209. protected boolean isPlainSupported() {
  210. return plainData != null;
  211. }
  212. /**
  213. * Fetch the data in a text/plain format.
  214. */
  215. protected String getPlainData() {
  216. return plainData;
  217. }
  218. // --- string flavorss --------------------------------------------------------
  219. /**
  220. * Returns whether or not the specified data flavor is a String flavor that
  221. * is supported.
  222. * @param flavor the requested flavor for the data
  223. * @return boolean indicating whether or not the data flavor is supported
  224. */
  225. protected boolean isStringFlavor(DataFlavor flavor) {
  226. DataFlavor[] flavors = stringFlavors;
  227. for (int i = 0; i < flavors.length; i++) {
  228. if (flavors[i].equals(flavor)) {
  229. return true;
  230. }
  231. }
  232. return false;
  233. }
  234. }