26 package java.awt.dnd; 27 28 import java.awt.Component; 29 30 import java.awt.datatransfer.DataFlavor; 31 import java.awt.datatransfer.Transferable; 32 import java.awt.datatransfer.UnsupportedFlavorException; 33 34 import java.awt.dnd.peer.DropTargetContextPeer; 35 36 import java.io.IOException; 37 import java.io.Serializable; 38 39 import java.util.Arrays; 40 import java.util.List; 41 42 import sun.awt.AWTAccessor; 43 import sun.awt.AWTAccessor.DropTargetContextAccessor; 44 45 /** 46 * A <code>DropTargetContext</code> is created 47 * whenever the logical cursor associated 48 * with a Drag and Drop operation coincides with the visible geometry of 49 * a <code>Component</code> associated with a <code>DropTarget</code>. 50 * The <code>DropTargetContext</code> provides 51 * the mechanism for a potential receiver 52 * of a drop operation to both provide the end user with the appropriate 53 * drag under feedback, but also to effect the subsequent data transfer 54 * if appropriate. 55 * 56 * @since 1.2 57 */ 58 59 public class DropTargetContext implements Serializable { 60 61 private static final long serialVersionUID = -634158968993743371L; 62 63 static { 64 AWTAccessor.setDropTargetContextAccessor(new DropTargetContextAccessor() { 65 @Override 66 public void reset(DropTargetContext dtc) { 67 dtc.reset(); 68 } 69 @Override 70 public void setDropTargetContextPeer(DropTargetContext dtc, 71 DropTargetContextPeer dtcp) { 72 dtc.setDropTargetContextPeer(dtcp); 73 } 74 }); 75 } 76 /** 77 * Construct a <code>DropTargetContext</code> 78 * given a specified <code>DropTarget</code>. 79 * 80 * @param dt the DropTarget to associate with 81 */ 82 83 DropTargetContext(DropTarget dt) { 84 super(); 85 86 dropTarget = dt; 87 } 88 89 /** 90 * This method returns the <code>DropTarget</code> associated with this 91 * <code>DropTargetContext</code>. 92 * 93 * @return the <code>DropTarget</code> associated with this <code>DropTargetContext</code> 94 */ 95 96 public DropTarget getDropTarget() { return dropTarget; } 97 98 /** 99 * This method returns the <code>Component</code> associated with 100 * this <code>DropTargetContext</code>. 101 * 102 * @return the Component associated with this Context 103 */ 104 105 public Component getComponent() { return dropTarget.getComponent(); } 106 107 /** 108 * Called when disassociated with the <code>DropTargetContextPeer</code>. 109 */ 110 void reset() { 111 dropTargetContextPeer = null; 112 transferable = null; 113 } 114 115 /** 116 * This method sets the current actions acceptable to 117 * this <code>DropTarget</code>. 118 * 119 * @param actions an <code>int</code> representing the supported action(s) 120 */ 121 122 protected void setTargetActions(int actions) { 123 DropTargetContextPeer peer = getDropTargetContextPeer(); 124 if (peer != null) { 125 synchronized (peer) { 126 peer.setTargetActions(actions); 127 getDropTarget().doSetDefaultActions(actions); 128 } 129 } else { 130 getDropTarget().doSetDefaultActions(actions); 131 } 132 } 133 134 /** 135 * This method returns an <code>int</code> representing the 136 * current actions this <code>DropTarget</code> will accept. 137 * 138 * @return the current actions acceptable to this <code>DropTarget</code> 139 */ 140 141 protected int getTargetActions() { 142 DropTargetContextPeer peer = getDropTargetContextPeer(); 143 return ((peer != null) 144 ? peer.getTargetActions() 145 : dropTarget.getDefaultActions() 146 ); 147 } 148 149 /** 150 * This method signals that the drop is completed and 151 * if it was successful or not. 152 * 153 * @param success true for success, false if not 154 * 155 * @throws InvalidDnDOperationException if a drop is not outstanding/extant 156 */ 157 158 public void dropComplete(boolean success) throws InvalidDnDOperationException{ 198 DropTargetContextPeer peer = getDropTargetContextPeer(); 199 if (peer != null) { 200 peer.acceptDrop(dropOperation); 201 } 202 } 203 204 /** 205 * called to signal that the drop is unacceptable. 206 * must be called during DropTargetListener.drop method invocation. 207 */ 208 209 protected void rejectDrop() { 210 DropTargetContextPeer peer = getDropTargetContextPeer(); 211 if (peer != null) { 212 peer.rejectDrop(); 213 } 214 } 215 216 /** 217 * get the available DataFlavors of the 218 * <code>Transferable</code> operand of this operation. 219 * 220 * @return a <code>DataFlavor[]</code> containing the 221 * supported <code>DataFlavor</code>s of the 222 * <code>Transferable</code> operand. 223 */ 224 225 protected DataFlavor[] getCurrentDataFlavors() { 226 DropTargetContextPeer peer = getDropTargetContextPeer(); 227 return peer != null ? peer.getTransferDataFlavors() : new DataFlavor[0]; 228 } 229 230 /** 231 * This method returns a the currently available DataFlavors 232 * of the <code>Transferable</code> operand 233 * as a <code>java.util.List</code>. 234 * 235 * @return the currently available 236 * DataFlavors as a <code>java.util.List</code> 237 */ 238 239 protected List<DataFlavor> getCurrentDataFlavorsAsList() { 240 return Arrays.asList(getCurrentDataFlavors()); 241 } 242 243 /** 244 * This method returns a <code>boolean</code> 245 * indicating if the given <code>DataFlavor</code> is 246 * supported by this <code>DropTargetContext</code>. 247 * 248 * @param df the <code>DataFlavor</code> 249 * 250 * @return if the <code>DataFlavor</code> specified is supported 251 */ 252 253 protected boolean isDataFlavorSupported(DataFlavor df) { 254 return getCurrentDataFlavorsAsList().contains(df); 255 } 256 257 /** 258 * get the Transferable (proxy) operand of this operation 259 * 260 * @throws InvalidDnDOperationException if a drag is not outstanding/extant 261 * 262 * @return the <code>Transferable</code> 263 */ 264 265 protected Transferable getTransferable() throws InvalidDnDOperationException { 266 DropTargetContextPeer peer = getDropTargetContextPeer(); 267 if (peer == null) { 268 throw new InvalidDnDOperationException(); 269 } else { 270 if (transferable == null) { 271 Transferable t = peer.getTransferable(); 272 boolean isLocal = peer.isTransferableJVMLocal(); 273 synchronized (this) { 274 if (transferable == null) { 275 transferable = createTransferableProxy(t, isLocal); 276 } 277 } 278 } 279 280 return transferable; 281 } 282 } 283 284 /** 285 * Get the <code>DropTargetContextPeer</code> 286 * 287 * @return the platform peer 288 */ 289 DropTargetContextPeer getDropTargetContextPeer() { 290 return dropTargetContextPeer; 291 } 292 293 /** 294 * Sets the {@code DropTargetContextPeer} 295 */ 296 void setDropTargetContextPeer(final DropTargetContextPeer dtcp) { 297 dropTargetContextPeer = dtcp; 298 } 299 300 /** 301 * Creates a TransferableProxy to proxy for the specified 302 * Transferable. 303 * 304 * @param t the <tt>Transferable</tt> to be proxied 305 * @param local <tt>true</tt> if <tt>t</tt> represents 306 * the result of a local drag-n-drop operation. 307 * @return the new <tt>TransferableProxy</tt> instance. 308 */ 309 protected Transferable createTransferableProxy(Transferable t, boolean local) { 310 return new TransferableProxy(t, local); 311 } 312 313 /****************************************************************************/ 314 315 316 /** 317 * <code>TransferableProxy</code> is a helper inner class that implements 318 * <code>Transferable</code> interface and serves as a proxy for another 319 * <code>Transferable</code> object which represents data transfer for 320 * a particular drag-n-drop operation. 321 * <p> 322 * The proxy forwards all requests to the encapsulated transferable 323 * and automatically performs additional conversion on the data 324 * returned by the encapsulated transferable in case of local transfer. 325 */ 326 327 protected class TransferableProxy implements Transferable { 328 329 /** 330 * Constructs a <code>TransferableProxy</code> given 331 * a specified <code>Transferable</code> object representing 332 * data transfer for a particular drag-n-drop operation and 333 * a <code>boolean</code> which indicates whether the 334 * drag-n-drop operation is local (within the same JVM). 335 * 336 * @param t the <code>Transferable</code> object 337 * @param local <code>true</code>, if <code>t</code> represents 338 * the result of local drag-n-drop operation 339 */ 340 TransferableProxy(Transferable t, boolean local) { 341 proxy = new sun.awt.datatransfer.TransferableProxy(t, local); 342 transferable = t; 343 isLocal = local; 344 } 345 346 /** 347 * Returns an array of DataFlavor objects indicating the flavors 348 * the data can be provided in by the encapsulated transferable. 349 * 350 * @return an array of data flavors in which the data can be 351 * provided by the encapsulated transferable 352 */ 353 public DataFlavor[] getTransferDataFlavors() { 354 return proxy.getTransferDataFlavors(); 355 } 356 357 /** 358 * Returns whether or not the specified data flavor is supported by 359 * the encapsulated transferable. 360 * @param flavor the requested flavor for the data 361 * @return <code>true</code> if the data flavor is supported, 362 * <code>false</code> otherwise 363 */ 364 public boolean isDataFlavorSupported(DataFlavor flavor) { 365 return proxy.isDataFlavorSupported(flavor); 366 } 367 368 /** 369 * Returns an object which represents the data provided by 370 * the encapsulated transferable for the requested data flavor. 371 * <p> 372 * In case of local transfer a serialized copy of the object 373 * returned by the encapsulated transferable is provided when 374 * the data is requested in application/x-java-serialized-object 375 * data flavor. 376 * 377 * @param df the requested flavor for the data 378 * @throws IOException if the data is no longer available 379 * in the requested flavor. 380 * @throws UnsupportedFlavorException if the requested data flavor is 381 * not supported. 382 */ 383 public Object getTransferData(DataFlavor df) 384 throws UnsupportedFlavorException, IOException 385 { 386 return proxy.getTransferData(df); 387 } 388 389 /* 390 * fields 391 */ 392 393 // We don't need to worry about client code changing the values of 394 // these variables. Since TransferableProxy is a protected class, only 395 // subclasses of DropTargetContext can access it. And DropTargetContext 396 // cannot be subclassed by client code because it does not have a 397 // public constructor. 398 399 /** 400 * The encapsulated <code>Transferable</code> object. 401 */ 402 protected Transferable transferable; 403 404 /** 405 * A <code>boolean</code> indicating if the encapsulated 406 * <code>Transferable</code> object represents the result 407 * of local drag-n-drop operation (within the same JVM). 408 */ 409 protected boolean isLocal; 410 411 private sun.awt.datatransfer.TransferableProxy proxy; 412 } 413 414 /****************************************************************************/ 415 416 /* 417 * fields 418 */ 419 420 /** 421 * The DropTarget associated with this DropTargetContext. 422 * 423 * @serial 424 */ 425 private final DropTarget dropTarget; 426 | 26 package java.awt.dnd; 27 28 import java.awt.Component; 29 30 import java.awt.datatransfer.DataFlavor; 31 import java.awt.datatransfer.Transferable; 32 import java.awt.datatransfer.UnsupportedFlavorException; 33 34 import java.awt.dnd.peer.DropTargetContextPeer; 35 36 import java.io.IOException; 37 import java.io.Serializable; 38 39 import java.util.Arrays; 40 import java.util.List; 41 42 import sun.awt.AWTAccessor; 43 import sun.awt.AWTAccessor.DropTargetContextAccessor; 44 45 /** 46 * A {@code DropTargetContext} is created 47 * whenever the logical cursor associated 48 * with a Drag and Drop operation coincides with the visible geometry of 49 * a {@code Component} associated with a {@code DropTarget}. 50 * The {@code DropTargetContext} provides 51 * the mechanism for a potential receiver 52 * of a drop operation to both provide the end user with the appropriate 53 * drag under feedback, but also to effect the subsequent data transfer 54 * if appropriate. 55 * 56 * @since 1.2 57 */ 58 59 public class DropTargetContext implements Serializable { 60 61 private static final long serialVersionUID = -634158968993743371L; 62 63 static { 64 AWTAccessor.setDropTargetContextAccessor(new DropTargetContextAccessor() { 65 @Override 66 public void reset(DropTargetContext dtc) { 67 dtc.reset(); 68 } 69 @Override 70 public void setDropTargetContextPeer(DropTargetContext dtc, 71 DropTargetContextPeer dtcp) { 72 dtc.setDropTargetContextPeer(dtcp); 73 } 74 }); 75 } 76 /** 77 * Construct a {@code DropTargetContext} 78 * given a specified {@code DropTarget}. 79 * 80 * @param dt the DropTarget to associate with 81 */ 82 83 DropTargetContext(DropTarget dt) { 84 super(); 85 86 dropTarget = dt; 87 } 88 89 /** 90 * This method returns the {@code DropTarget} associated with this 91 * {@code DropTargetContext}. 92 * 93 * @return the {@code DropTarget} associated with this {@code DropTargetContext} 94 */ 95 96 public DropTarget getDropTarget() { return dropTarget; } 97 98 /** 99 * This method returns the {@code Component} associated with 100 * this {@code DropTargetContext}. 101 * 102 * @return the Component associated with this Context 103 */ 104 105 public Component getComponent() { return dropTarget.getComponent(); } 106 107 /** 108 * Called when disassociated with the {@code DropTargetContextPeer}. 109 */ 110 void reset() { 111 dropTargetContextPeer = null; 112 transferable = null; 113 } 114 115 /** 116 * This method sets the current actions acceptable to 117 * this {@code DropTarget}. 118 * 119 * @param actions an {@code int} representing the supported action(s) 120 */ 121 122 protected void setTargetActions(int actions) { 123 DropTargetContextPeer peer = getDropTargetContextPeer(); 124 if (peer != null) { 125 synchronized (peer) { 126 peer.setTargetActions(actions); 127 getDropTarget().doSetDefaultActions(actions); 128 } 129 } else { 130 getDropTarget().doSetDefaultActions(actions); 131 } 132 } 133 134 /** 135 * This method returns an {@code int} representing the 136 * current actions this {@code DropTarget} will accept. 137 * 138 * @return the current actions acceptable to this {@code DropTarget} 139 */ 140 141 protected int getTargetActions() { 142 DropTargetContextPeer peer = getDropTargetContextPeer(); 143 return ((peer != null) 144 ? peer.getTargetActions() 145 : dropTarget.getDefaultActions() 146 ); 147 } 148 149 /** 150 * This method signals that the drop is completed and 151 * if it was successful or not. 152 * 153 * @param success true for success, false if not 154 * 155 * @throws InvalidDnDOperationException if a drop is not outstanding/extant 156 */ 157 158 public void dropComplete(boolean success) throws InvalidDnDOperationException{ 198 DropTargetContextPeer peer = getDropTargetContextPeer(); 199 if (peer != null) { 200 peer.acceptDrop(dropOperation); 201 } 202 } 203 204 /** 205 * called to signal that the drop is unacceptable. 206 * must be called during DropTargetListener.drop method invocation. 207 */ 208 209 protected void rejectDrop() { 210 DropTargetContextPeer peer = getDropTargetContextPeer(); 211 if (peer != null) { 212 peer.rejectDrop(); 213 } 214 } 215 216 /** 217 * get the available DataFlavors of the 218 * {@code Transferable} operand of this operation. 219 * 220 * @return a {@code DataFlavor[]} containing the 221 * supported {@code DataFlavor}s of the 222 * {@code Transferable} operand. 223 */ 224 225 protected DataFlavor[] getCurrentDataFlavors() { 226 DropTargetContextPeer peer = getDropTargetContextPeer(); 227 return peer != null ? peer.getTransferDataFlavors() : new DataFlavor[0]; 228 } 229 230 /** 231 * This method returns a the currently available DataFlavors 232 * of the {@code Transferable} operand 233 * as a {@code java.util.List}. 234 * 235 * @return the currently available 236 * DataFlavors as a {@code java.util.List} 237 */ 238 239 protected List<DataFlavor> getCurrentDataFlavorsAsList() { 240 return Arrays.asList(getCurrentDataFlavors()); 241 } 242 243 /** 244 * This method returns a {@code boolean} 245 * indicating if the given {@code DataFlavor} is 246 * supported by this {@code DropTargetContext}. 247 * 248 * @param df the {@code DataFlavor} 249 * 250 * @return if the {@code DataFlavor} specified is supported 251 */ 252 253 protected boolean isDataFlavorSupported(DataFlavor df) { 254 return getCurrentDataFlavorsAsList().contains(df); 255 } 256 257 /** 258 * get the Transferable (proxy) operand of this operation 259 * 260 * @throws InvalidDnDOperationException if a drag is not outstanding/extant 261 * 262 * @return the {@code Transferable} 263 */ 264 265 protected Transferable getTransferable() throws InvalidDnDOperationException { 266 DropTargetContextPeer peer = getDropTargetContextPeer(); 267 if (peer == null) { 268 throw new InvalidDnDOperationException(); 269 } else { 270 if (transferable == null) { 271 Transferable t = peer.getTransferable(); 272 boolean isLocal = peer.isTransferableJVMLocal(); 273 synchronized (this) { 274 if (transferable == null) { 275 transferable = createTransferableProxy(t, isLocal); 276 } 277 } 278 } 279 280 return transferable; 281 } 282 } 283 284 /** 285 * Get the {@code DropTargetContextPeer} 286 * 287 * @return the platform peer 288 */ 289 DropTargetContextPeer getDropTargetContextPeer() { 290 return dropTargetContextPeer; 291 } 292 293 /** 294 * Sets the {@code DropTargetContextPeer} 295 */ 296 void setDropTargetContextPeer(final DropTargetContextPeer dtcp) { 297 dropTargetContextPeer = dtcp; 298 } 299 300 /** 301 * Creates a TransferableProxy to proxy for the specified 302 * Transferable. 303 * 304 * @param t the {@code Transferable} to be proxied 305 * @param local {@code true} if {@code t} represents 306 * the result of a local drag-n-drop operation. 307 * @return the new {@code TransferableProxy} instance. 308 */ 309 protected Transferable createTransferableProxy(Transferable t, boolean local) { 310 return new TransferableProxy(t, local); 311 } 312 313 /****************************************************************************/ 314 315 316 /** 317 * {@code TransferableProxy} is a helper inner class that implements 318 * {@code Transferable} interface and serves as a proxy for another 319 * {@code Transferable} object which represents data transfer for 320 * a particular drag-n-drop operation. 321 * <p> 322 * The proxy forwards all requests to the encapsulated transferable 323 * and automatically performs additional conversion on the data 324 * returned by the encapsulated transferable in case of local transfer. 325 */ 326 327 protected class TransferableProxy implements Transferable { 328 329 /** 330 * Constructs a {@code TransferableProxy} given 331 * a specified {@code Transferable} object representing 332 * data transfer for a particular drag-n-drop operation and 333 * a {@code boolean} which indicates whether the 334 * drag-n-drop operation is local (within the same JVM). 335 * 336 * @param t the {@code Transferable} object 337 * @param local {@code true}, if {@code t} represents 338 * the result of local drag-n-drop operation 339 */ 340 TransferableProxy(Transferable t, boolean local) { 341 proxy = new sun.awt.datatransfer.TransferableProxy(t, local); 342 transferable = t; 343 isLocal = local; 344 } 345 346 /** 347 * Returns an array of DataFlavor objects indicating the flavors 348 * the data can be provided in by the encapsulated transferable. 349 * 350 * @return an array of data flavors in which the data can be 351 * provided by the encapsulated transferable 352 */ 353 public DataFlavor[] getTransferDataFlavors() { 354 return proxy.getTransferDataFlavors(); 355 } 356 357 /** 358 * Returns whether or not the specified data flavor is supported by 359 * the encapsulated transferable. 360 * @param flavor the requested flavor for the data 361 * @return {@code true} if the data flavor is supported, 362 * {@code false} otherwise 363 */ 364 public boolean isDataFlavorSupported(DataFlavor flavor) { 365 return proxy.isDataFlavorSupported(flavor); 366 } 367 368 /** 369 * Returns an object which represents the data provided by 370 * the encapsulated transferable for the requested data flavor. 371 * <p> 372 * In case of local transfer a serialized copy of the object 373 * returned by the encapsulated transferable is provided when 374 * the data is requested in application/x-java-serialized-object 375 * data flavor. 376 * 377 * @param df the requested flavor for the data 378 * @throws IOException if the data is no longer available 379 * in the requested flavor. 380 * @throws UnsupportedFlavorException if the requested data flavor is 381 * not supported. 382 */ 383 public Object getTransferData(DataFlavor df) 384 throws UnsupportedFlavorException, IOException 385 { 386 return proxy.getTransferData(df); 387 } 388 389 /* 390 * fields 391 */ 392 393 // We don't need to worry about client code changing the values of 394 // these variables. Since TransferableProxy is a protected class, only 395 // subclasses of DropTargetContext can access it. And DropTargetContext 396 // cannot be subclassed by client code because it does not have a 397 // public constructor. 398 399 /** 400 * The encapsulated {@code Transferable} object. 401 */ 402 protected Transferable transferable; 403 404 /** 405 * A {@code boolean} indicating if the encapsulated 406 * {@code Transferable} object represents the result 407 * of local drag-n-drop operation (within the same JVM). 408 */ 409 protected boolean isLocal; 410 411 private sun.awt.datatransfer.TransferableProxy proxy; 412 } 413 414 /****************************************************************************/ 415 416 /* 417 * fields 418 */ 419 420 /** 421 * The DropTarget associated with this DropTargetContext. 422 * 423 * @serial 424 */ 425 private final DropTarget dropTarget; 426 |