1 7 package javax.swing; 8 9 import java.awt.*; 10 import java.awt.event.*; 11 import java.awt.datatransfer.*; 12 import java.awt.dnd.*; 13 import java.beans.*; 14 import java.lang.reflect.*; 15 import java.io.*; 16 import java.util.TooManyListenersException ; 17 import javax.swing.plaf.UIResource ; 18 import javax.swing.event.*; 19 20 import com.sun.java.swing.SwingUtilities2; 21 import sun.reflect.misc.MethodUtil; 22 23 55 public class TransferHandler implements Serializable { 56 57 60 public static final int NONE = DnDConstants.ACTION_NONE; 61 62 67 public static final int COPY = DnDConstants.ACTION_COPY; 68 69 74 public static final int MOVE = DnDConstants.ACTION_MOVE; 75 76 80 public static final int COPY_OR_MOVE = DnDConstants.ACTION_COPY_OR_MOVE; 81 82 87 private static final int LINK = DnDConstants.ACTION_LINK; 88 89 90 99 public static Action getCutAction() { 100 return cutAction; 101 } 102 103 112 public static Action getCopyAction() { 113 return copyAction; 114 } 115 116 125 public static Action getPasteAction() { 126 return pasteAction; 127 } 128 129 130 139 public TransferHandler(String property) { 140 propertyName = property; 141 } 142 143 146 protected TransferHandler() { 147 this(null); 148 } 149 150 174 public void exportAsDrag(JComponent comp, InputEvent e, int action) { 175 int srcActions = getSourceActions(comp); 176 int dragAction = srcActions & action; 177 if (! (e instanceof MouseEvent)) { 178 dragAction = NONE; 180 } 181 if (dragAction != NONE && !GraphicsEnvironment.isHeadless()) { 182 if (recognizer == null) { 183 recognizer = new SwingDragGestureRecognizer(new DragHandler()); 184 } 185 recognizer.gestured(comp, (MouseEvent)e, srcActions, dragAction); 186 } else { 187 exportDone(comp, null, NONE); 188 } 189 } 190 191 220 public void exportToClipboard(JComponent comp, Clipboard clip, int action) 221 throws IllegalStateException { 222 223 int clipboardAction = getSourceActions(comp) & action; 224 if (clipboardAction != NONE) { 225 Transferable t = createTransferable(comp); 226 if (t != null) { 227 try { 228 clip.setContents(t, null); 229 exportDone(comp, t, clipboardAction); 230 return; 231 } catch (IllegalStateException ise) { 232 exportDone(comp, t, NONE); 233 throw ise; 234 } 235 } 236 } 237 238 exportDone(comp, null, NONE); 239 } 240 241 252 public boolean importData(JComponent comp, Transferable t) { 253 PropertyDescriptor prop = getPropertyDescriptor(comp); 254 if (prop != null) { 255 Method writer = prop.getWriteMethod(); 256 if (writer == null) { 257 return false; 259 } 260 Class [] params = writer.getParameterTypes(); 261 if (params.length != 1) { 262 return false; 264 } 265 DataFlavor flavor = getPropertyDataFlavor(params[0], t.getTransferDataFlavors()); 266 if (flavor != null) { 267 try { 268 Object value = t.getTransferData(flavor); 269 Object [] args = { value }; 270 MethodUtil.invoke(writer, comp, args); 271 return true; 272 } catch (Exception ex) { 273 System.err.println("Invocation failed"); 274 } 276 } 277 } 278 return false; 279 } 280 281 291 public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) { 292 PropertyDescriptor prop = getPropertyDescriptor(comp); 293 if (prop != null) { 294 Method writer = prop.getWriteMethod(); 295 if (writer == null) { 296 return false; 298 } 299 Class [] params = writer.getParameterTypes(); 300 if (params.length != 1) { 301 return false; 303 } 304 DataFlavor flavor = getPropertyDataFlavor(params[0], transferFlavors); 305 if (flavor != null) { 306 return true; 307 } 308 } 309 return false; 310 } 311 312 324 public int getSourceActions(JComponent c) { 325 PropertyDescriptor prop = getPropertyDescriptor(c); 326 if (prop != null) { 327 return COPY; 328 } 329 return NONE; 330 } 331 332 353 public Icon getVisualRepresentation(Transferable t) { 354 return null; 355 } 356 357 371 protected Transferable createTransferable(JComponent c) { 372 PropertyDescriptor property = getPropertyDescriptor(c); 373 if (property != null) { 374 return new PropertyTransferable(property, c); 375 } 376 return null; 377 } 378 379 392 protected void exportDone(JComponent source, Transferable data, int action) { 393 } 394 395 401 private PropertyDescriptor getPropertyDescriptor(JComponent comp) { 402 if (propertyName == null) { 403 return null; 404 } 405 Class k = comp.getClass(); 406 BeanInfo bi; 407 try { 408 bi = Introspector.getBeanInfo(k); 409 } catch (IntrospectionException ex) { 410 return null; 411 } 412 PropertyDescriptor props[] = bi.getPropertyDescriptors(); 413 for (int i=0; i < props.length; i++) { 414 if (propertyName.equals(props[i].getName())) { 415 Method reader = props[i].getReadMethod(); 416 417 if (reader != null) { 418 Class [] params = reader.getParameterTypes(); 419 420 if (params == null || params.length == 0) { 421 return props[i]; 423 } 424 } 425 } 426 } 427 return null; 428 } 429 430 435 private DataFlavor getPropertyDataFlavor(Class k, DataFlavor[] flavors) { 436 for(int i = 0; i < flavors.length; i++) { 437 DataFlavor flavor = flavors[i]; 438 if ("application".equals(flavor.getPrimaryType()) && 439 "x-java-jvm-local-objectref".equals(flavor.getSubType()) && 440 k.isAssignableFrom(flavor.getRepresentationClass())) { 441 442 return flavor; 443 } 444 } 445 return null; 446 } 447 448 449 private String propertyName; 450 private static SwingDragGestureRecognizer recognizer = null; 451 private static DropTargetListener dropLinkage = null; 452 453 private static DropTargetListener getDropTargetListener() { 454 if (dropLinkage == null) { 455 dropLinkage = new DropHandler(); 456 } 457 return dropLinkage; 458 } 459 460 static class PropertyTransferable implements Transferable { 461 462 PropertyTransferable(PropertyDescriptor p, JComponent c) { 463 property = p; 464 component = c; 465 } 466 467 469 475 public DataFlavor[] getTransferDataFlavors() { 476 DataFlavor[] flavors = new DataFlavor[1]; 477 Class propertyType = property.getPropertyType(); 478 String mimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=" + propertyType.getName(); 479 try { 480 flavors[0] = new DataFlavor(mimeType); 481 } catch (ClassNotFoundException cnfe) { 482 flavors = new DataFlavor[0]; 483 } 484 return flavors; 485 } 486 487 494 public boolean isDataFlavorSupported(DataFlavor flavor) { 495 Class propertyType = property.getPropertyType(); 496 if ("application".equals(flavor.getPrimaryType()) && 497 "x-java-jvm-local-objectref".equals(flavor.getSubType()) && 498 flavor.getRepresentationClass().isAssignableFrom(propertyType)) { 499 500 return true; 501 } 502 return false; 503 } 504 505 516 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { 517 if (! isDataFlavorSupported(flavor)) { 518 throw new UnsupportedFlavorException(flavor); 519 } 520 Method reader = property.getReadMethod(); 521 Object value = null; 522 try { 523 value = MethodUtil.invoke(reader, component, null); 524 } catch (Exception ex) { 525 throw new IOException("Property read failed: " + property.getName()); 526 } 527 return value; 528 } 529 530 JComponent component; 531 PropertyDescriptor property; 532 } 533 534 544 static class SwingDropTarget extends DropTarget implements UIResource { 545 546 SwingDropTarget(JComponent c) { 547 super(); 548 setComponent(c); 549 try { 550 super.addDropTargetListener(getDropTargetListener()); 551 } catch (TooManyListenersException tmle) {} 552 } 553 554 public void addDropTargetListener(DropTargetListener dtl) throws TooManyListenersException { 555 if (listenerList == null) { 559 listenerList = new EventListenerList(); 560 } 561 listenerList.add(DropTargetListener.class, dtl); 562 } 563 564 public void removeDropTargetListener(DropTargetListener dtl) { 565 if (listenerList != null) { 566 listenerList.remove(DropTargetListener.class, dtl); 567 } 568 } 569 570 572 public void dragEnter(DropTargetDragEvent e) { 573 super.dragEnter(e); 574 if (listenerList != null) { 575 Object [] listeners = listenerList.getListenerList(); 576 for (int i = listeners.length-2; i>=0; i-=2) { 577 if (listeners[i]==DropTargetListener.class) { 578 ((DropTargetListener)listeners[i+1]).dragEnter(e); 579 } 580 } 581 } 582 } 583 584 public void dragOver(DropTargetDragEvent e) { 585 super.dragOver(e); 586 if (listenerList != null) { 587 Object [] listeners = listenerList.getListenerList(); 588 for (int i = listeners.length-2; i>=0; i-=2) { 589 if (listeners[i]==DropTargetListener.class) { 590 ((DropTargetListener)listeners[i+1]).dragOver(e); 591 } 592 } 593 } 594 } 595 596 public void dragExit(DropTargetEvent e) { 597 super.dragExit(e); 598 if (listenerList != null) { 599 Object [] listeners = listenerList.getListenerList(); 600 for (int i = listeners.length-2; i>=0; i-=2) { 601 if (listeners[i]==DropTargetListener.class) { 602 ((DropTargetListener)listeners[i+1]).dragExit(e); 603 } 604 } 605 } 606 } 607 608 public void drop(DropTargetDropEvent e) { 609 super.drop(e); 610 if (listenerList != null) { 611 Object [] listeners = listenerList.getListenerList(); 612 for (int i = listeners.length-2; i>=0; i-=2) { 613 if (listeners[i]==DropTargetListener.class) { 614 ((DropTargetListener)listeners[i+1]).drop(e); 615 } 616 } 617 } 618 } 619 620 public void dropActionChanged(DropTargetDragEvent e) { 621 super.dropActionChanged(e); 622 if (listenerList != null) { 623 Object [] listeners = listenerList.getListenerList(); 624 for (int i = listeners.length-2; i>=0; i-=2) { 625 if (listeners[i]==DropTargetListener.class) { 626 ((DropTargetListener)listeners[i+1]).dropActionChanged(e); 627 } 628 } 629 } 630 } 631 632 private EventListenerList listenerList; 633 } 634 635 private static class DropHandler implements DropTargetListener, Serializable { 636 637 private boolean canImport; 638 639 private boolean actionSupported(int action) { 640 return (action & (COPY_OR_MOVE | LINK)) != NONE; 641 } 642 643 645 public void dragEnter(DropTargetDragEvent e) { 646 DataFlavor[] flavors = e.getCurrentDataFlavors(); 647 648 JComponent c = (JComponent )e.getDropTargetContext().getComponent(); 649 TransferHandler importer = c.getTransferHandler(); 650 651 if (importer != null && importer.canImport(c, flavors)) { 652 canImport = true; 653 } else { 654 canImport = false; 655 } 656 657 int dropAction = e.getDropAction(); 658 659 if (canImport && actionSupported(dropAction)) { 660 e.acceptDrag(dropAction); 661 } else { 662 e.rejectDrag(); 663 } 664 } 665 666 public void dragOver(DropTargetDragEvent e) { 667 int dropAction = e.getDropAction(); 668 669 if (canImport && actionSupported(dropAction)) { 670 e.acceptDrag(dropAction); 671 } else { 672 e.rejectDrag(); 673 } 674 } 675 676 public void dragExit(DropTargetEvent e) { 677 } 678 679 public void drop(DropTargetDropEvent e) { 680 int dropAction = e.getDropAction(); 681 682 JComponent c = (JComponent )e.getDropTargetContext().getComponent(); 683 TransferHandler importer = c.getTransferHandler(); 684 685 if (canImport && importer != null && actionSupported(dropAction)) { 686 e.acceptDrop(dropAction); 687 688 try { 689 Transferable t = e.getTransferable(); 690 e.dropComplete(importer.importData(c, t)); 691 } catch (RuntimeException re) { 692 e.dropComplete(false); 693 } 694 } else { 695 e.rejectDrop(); 696 } 697 } 698 699 public void dropActionChanged(DropTargetDragEvent e) { 700 int dropAction = e.getDropAction(); 701 702 if (canImport && actionSupported(dropAction)) { 703 e.acceptDrag(dropAction); 704 } else { 705 e.rejectDrag(); 706 } 707 } 708 } 709 710 714 private static class DragHandler implements DragGestureListener, DragSourceListener { 715 716 private boolean scrolls; 717 718 720 723 public void dragGestureRecognized(DragGestureEvent dge) { 724 JComponent c = (JComponent ) dge.getComponent(); 725 TransferHandler th = c.getTransferHandler(); 726 Transferable t = th.createTransferable(c); 727 if (t != null) { 728 scrolls = c.getAutoscrolls(); 729 c.setAutoscrolls(false); 730 try { 731 dge.startDrag(null, t, this); 732 return; 733 } catch (RuntimeException re) { 734 c.setAutoscrolls(scrolls); 735 } 736 } 737 738 th.exportDone(c, t, NONE); 739 } 740 741 743 746 public void dragEnter(DragSourceDragEvent dsde) { 747 } 748 749 752 public void dragOver(DragSourceDragEvent dsde) { 753 } 754 755 758 public void dragExit(DragSourceEvent dsde) { 759 } 760 761 764 public void dragDropEnd(DragSourceDropEvent dsde) { 765 DragSourceContext dsc = dsde.getDragSourceContext(); 766 JComponent c = (JComponent )dsc.getComponent(); 767 if (dsde.getDropSuccess()) { 768 c.getTransferHandler().exportDone(c, dsc.getTransferable(), dsde.getDropAction()); 769 } else { 770 c.getTransferHandler().exportDone(c, dsc.getTransferable(), NONE); 771 } 772 c.setAutoscrolls(scrolls); 773 } 774 775 public void dropActionChanged(DragSourceDragEvent dsde) { 776 } 777 } 778 779 private static class SwingDragGestureRecognizer extends DragGestureRecognizer { 780 781 SwingDragGestureRecognizer(DragGestureListener dgl) { 782 super(DragSource.getDefaultDragSource(), null, NONE, dgl); 783 } 784 785 void gestured(JComponent c, MouseEvent e, int srcActions, int action) { 786 setComponent(c); 787 setSourceActions(srcActions); 788 appendEvent(e); 789 fireDragGestureRecognized(action, e.getPoint()); 790 } 791 792 795 protected void registerListeners() { 796 } 797 798 803 protected void unregisterListeners() { 804 } 805 806 } 807 808 static final Action cutAction = new TransferAction("cut"); 809 static final Action copyAction = new TransferAction("copy"); 810 static final Action pasteAction = new TransferAction("paste"); 811 812 static class TransferAction extends AbstractAction implements UIResource { 813 814 TransferAction(String name) { 815 super(name); 816 } 817 818 public void actionPerformed(ActionEvent e) { 819 Object src = e.getSource(); 820 if (src instanceof JComponent ) { 821 JComponent c = (JComponent ) src; 822 TransferHandler th = c.getTransferHandler(); 823 Clipboard clipboard = getClipboard(c); 824 String name = (String ) getValue(Action.NAME); 825 826 Transferable trans = null; 827 828 try { 830 if ((clipboard != null) && (th != null) && (name != null)) { 831 if ("cut".equals(name)) { 832 th.exportToClipboard(c, clipboard, MOVE); 833 } else if ("copy".equals(name)) { 834 th.exportToClipboard(c, clipboard, COPY); 835 } else if ("paste".equals(name)) { 836 trans = clipboard.getContents(null); 837 } 838 } 839 } catch (IllegalStateException ise) { 840 UIManager.getLookAndFeel().provideErrorFeedback(c); 842 return; 843 } 844 845 if (trans != null) { 847 th.importData(c, trans); 848 } 849 } 850 } 851 852 855 private Clipboard getClipboard(JComponent c) { 856 if (SwingUtilities2.canAccessSystemClipboard()) { 857 return c.getToolkit().getSystemClipboard(); 858 } 859 Clipboard clipboard = (Clipboard)sun.awt.AppContext.getAppContext(). 860 get(SandboxClipboardKey); 861 if (clipboard == null) { 862 clipboard = new Clipboard("Sandboxed Component Clipboard"); 863 sun.awt.AppContext.getAppContext().put(SandboxClipboardKey, 864 clipboard); 865 } 866 return clipboard; 867 } 868 869 873 private static Object SandboxClipboardKey = new Object (); 874 875 } 876 877 } 878 879 880 881 | Popular Tags |