001package jmri.util.iharder.dnd; 002 003import java.awt.datatransfer.DataFlavor; 004 005/** 006 * At last an easy way to encapsulate your custom objects for dragging and 007 * dropping in your Java programs! When you need to create a 008 * {@link java.awt.datatransfer.Transferable} object, use this class to wrap 009 * your object. For example: 010 * <pre><code> 011 * ... 012 * MyCoolClass myObj = new MyCoolClass(); 013 * Transferable xfer = new TransferableObject( myObj ); 014 * ... 015 * </code></pre> Or if you need to know when the data was actually dropped, like 016 * when you're moving data out of a list, say, you can use the 017 * {@link TransferableObject.Fetcher} inner class to return your object Just in 018 * Time. For example: 019 * <pre><code> 020 * ... 021 * final MyCoolClass myObj = new MyCoolClass(); 022 * 023 * TransferableObject.Fetcher fetcher = new TransferableObject.Fetcher() 024 * { public Object getObject(){ return myObj; } 025 * }; // end fetcher 026 * 027 * Transferable xfer = new TransferableObject( fetcher ); 028 * ... 029 * </code></pre> 030 * 031 * The {@link java.awt.datatransfer.DataFlavor} associated with 032 * {@link TransferableObject} has the representation class 033 * {@code net.iharder.dnd.TransferableObject.class} and MIME type 034 * {@code application/x-net.iharder.dnd.TransferableObject}. This data flavor 035 * is accessible via the static {@link #DATA_FLAVOR} property. 036 * 037 * <p> 038 * <em>This code is licensed for public use under the Common Public License 039 * version 0.5.</em><br> 040 * The Common Public License, developed by IBM and modeled after their 041 * industry-friendly IBM Public License, differs from other common open source 042 * licenses in several important ways: 043 * <ul> 044 * <li>You may include this software with other software that uses a different 045 * (even non-open source) license.</li> 046 * <li>You may use this software to make for-profit software.</li> 047 * <li>Your patent rights, should you generate patents, are protected.</li> 048 * </ul> 049 * <p> 050 * <em>Copyright 2001 Robert Harder</em> 051 * 052 * @author Robert.Harder copyright 2001 053 * @version 1.1 054 */ 055public class TransferableObject implements java.awt.datatransfer.Transferable { 056 057 /** 058 * The MIME type for {@link #DATA_FLAVOR} is 059 * {@code application/x-net.iharder.dnd.TransferableObject}. 060 * 061 * @since 1.1 062 */ 063 public final static String MIME_TYPE = "application/x-net.iharder.dnd.TransferableObject"; 064 065 /** 066 * The default {@link java.awt.datatransfer.DataFlavor} for 067 * {@link TransferableObject} has the representation class 068 * {@code net.iharder.dnd.TransferableObject.class} 069 * and the MIME type 070 * {@code application/x-net.iharder.dnd.TransferableObject}. 071 * 072 * @since 1.1 073 */ 074 public final static java.awt.datatransfer.DataFlavor DATA_FLAVOR 075 = new DataFlavor(jmri.util.iharder.dnd.TransferableObject.class, MIME_TYPE); 076 077 private Fetcher fetcher; 078 private Object data; 079 080 private java.awt.datatransfer.DataFlavor customFlavor; 081 082 /** 083 * Creates a new {@link TransferableObject} that wraps <var>data</var>. 084 * Along with the {@link #DATA_FLAVOR} associated with this class, this 085 * creates a custom data flavor with a representation class determined from 086 * <code>data.getClass()</code> and the MIME type 087 * {@code application/x-net.iharder.dnd.TransferableObject}. 088 * 089 * @param data The data to transfer 090 * @since 1.1 091 */ 092 public TransferableObject(Object data) { 093 this.data = data; 094 this.customFlavor = new java.awt.datatransfer.DataFlavor(data.getClass(), MIME_TYPE); 095 } // end constructor 096 097 /** 098 * Creates a new {@link TransferableObject} that will return the object that 099 * is returned by <var>fetcher</var>. No custom data flavor is set other 100 * than the default {@link #DATA_FLAVOR}. 101 * 102 * @see Fetcher 103 * @param fetcher The {@link Fetcher} that will return the data object 104 * @since 1.1 105 */ 106 public TransferableObject(Fetcher fetcher) { 107 this.fetcher = fetcher; 108 } // end constructor 109 110 /** 111 * Creates a new {@link TransferableObject} that will return the object that 112 * is returned by <var>fetcher</var>. Along with the {@link #DATA_FLAVOR} 113 * associated with this class, this creates a custom data flavor with a 114 * representation class <var>dataClass</var> 115 * and the MIME type 116 * {@code application/x-net.iharder.dnd.TransferableObject}. 117 * 118 * @see Fetcher 119 * @param dataClass The {@link java.lang.Class} to use in the custom data 120 * flavor 121 * @param fetcher The {@link Fetcher} that will return the data object 122 * @since 1.1 123 */ 124 public TransferableObject(Class<?> dataClass, Fetcher fetcher) { 125 this.fetcher = fetcher; 126 this.customFlavor = new java.awt.datatransfer.DataFlavor(dataClass, MIME_TYPE); 127 } // end constructor 128 129 /** 130 * Returns the custom {@link java.awt.datatransfer.DataFlavor} associated 131 * with the encapsulated object or {@code null} if the {@link Fetcher} 132 * constructor was used without passing a {@link java.lang.Class}. 133 * 134 * @return The custom data flavor for the encapsulated object 135 * @since 1.1 136 */ 137 public java.awt.datatransfer.DataFlavor getCustomDataFlavor() { 138 return customFlavor; 139 } // end getCustomDataFlavor 140 141 /* ******** T R A N S F E R A B L E M E T H O D S ******** */ 142 /** 143 * Returns a two- or three-element array containing first the custom data 144 * flavor, if one was created in the constructors, second the default 145 * DATA_FLAVOR associated with the TransferableObject, and third the 146 * java.awt.datatransfer.DataFlavor.stringFlavor. 147 * 148 * @return An array of supported data flavors 149 * @since 1.1 150 */ 151 @Override 152 public java.awt.datatransfer.DataFlavor[] getTransferDataFlavors() { 153 if (customFlavor != null) { 154 return new java.awt.datatransfer.DataFlavor[]{customFlavor, 155 DATA_FLAVOR, 156 java.awt.datatransfer.DataFlavor.stringFlavor 157 }; // end flavors array 158 } else { 159 return new java.awt.datatransfer.DataFlavor[]{DATA_FLAVOR, 160 java.awt.datatransfer.DataFlavor.stringFlavor 161 }; // end flavors array 162 } 163 } // end getTransferDataFlavors 164 165 /** 166 * Returns the data encapsulated in this {@link TransferableObject}. If the 167 * {@link Fetcher} constructor was used, then this is when the 168 * {@link Fetcher#getObject getObject()} method will be called. If the 169 * requested data flavor is not supported, then the 170 * {@link Fetcher#getObject getObject()} method will not be called. 171 * 172 * @param flavor The data flavor for the data to return 173 * @return The dropped data 174 * @since 1.1 175 */ 176 @Override 177 public Object getTransferData(java.awt.datatransfer.DataFlavor flavor) 178 throws java.awt.datatransfer.UnsupportedFlavorException, java.io.IOException { 179 // Native object 180 if (flavor.equals(DATA_FLAVOR)) { 181 return fetcher == null ? data : fetcher.getObject(); 182 } 183 184 // String 185 if (flavor.equals(java.awt.datatransfer.DataFlavor.stringFlavor)) { 186 return fetcher == null ? data.toString() : fetcher.getObject().toString(); 187 } 188 189 // We can't do anything else 190 throw new java.awt.datatransfer.UnsupportedFlavorException(flavor); 191 } // end getTransferData 192 193 /** 194 * Returns {@code true} if <var>flavor</var> is one of the supported 195 * flavors. Flavors are supported using the <code>equals(...)</code> method. 196 * 197 * @param flavor The data flavor to check 198 * @return Whether or not the flavor is supported 199 * @since 1.1 200 */ 201 @Override 202 public boolean isDataFlavorSupported(java.awt.datatransfer.DataFlavor flavor) { 203 // Native object 204 if (flavor.equals(DATA_FLAVOR)) { 205 return true; 206 } 207 208 // String 209 if (flavor.equals(java.awt.datatransfer.DataFlavor.stringFlavor)) { 210 return true; 211 } 212 213 // We can't do anything else 214 return false; 215 } // end isDataFlavorSupported 216 217 /* ******** I N N E R I N T E R F A C E F E T C H E R ******** */ 218 /** 219 * Instead of passing your data directly to the {@link TransferableObject} 220 * constructor, you may want to know exactly when your data was received in 221 * case you need to remove it from its source (or do anyting else to it). 222 * When the {@link #getTransferData getTransferData(...)} method is called 223 * on the {@link TransferableObject}, the {@link Fetcher}'s 224 * {@link #getObject getObject()} method will be called. 225 * 226 * @author Robert Harder copyright 2001 227 * @version 1.1 228 * @since 1.1 229 */ 230 public static interface Fetcher { 231 232 /** 233 * Return the object being encapsulated in the 234 * {@link TransferableObject}. 235 * 236 * @return The dropped object 237 * @since 1.1 238 */ 239 public abstract Object getObject(); 240 } // end inner interface Fetcher 241 242} // end class TransferableObject