1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65:
66: public class TransferHandler implements Serializable
67: {
68:
69:
73: private static class PropertyTransferable
74: implements Transferable
75: {
76:
79: private JComponent component;
80:
81:
84: private PropertyDescriptor property;
85:
86:
92: PropertyTransferable(JComponent c, PropertyDescriptor prop)
93: {
94: component = c;
95: property = prop;
96: }
97:
98:
103: public DataFlavor[] getTransferDataFlavors()
104: {
105: DataFlavor[] flavors;
106: Class propClass = property.getPropertyType();
107: String mime = DataFlavor.javaJVMLocalObjectMimeType + "; class="
108: + propClass.getName();
109: try
110: {
111: DataFlavor flavor = new DataFlavor(mime);
112: flavors = new DataFlavor[]{ flavor };
113: }
114: catch (ClassNotFoundException ex)
115: {
116: flavors = new DataFlavor[0];
117: }
118: return flavors;
119: }
120:
121:
128: public boolean isDataFlavorSupported(DataFlavor flavor)
129: {
130: Class propClass = property.getPropertyType();
131: return flavor.getPrimaryType().equals("application")
132: && flavor.getSubType().equals("x-java-jvm-local-objectref")
133: && propClass.isAssignableFrom(flavor.getRepresentationClass());
134: }
135:
136:
143: public Object getTransferData(DataFlavor flavor)
144: throws UnsupportedFlavorException, IOException
145: {
146: if (isDataFlavorSupported(flavor))
147: {
148: Method getter = property.getReadMethod();
149: Object o;
150: try
151: {
152: o = getter.invoke(component);
153: return o;
154: }
155: catch (Exception ex)
156: {
157: throw new IOException("Property read failed: "
158: + property.getName());
159: }
160: }
161: else
162: throw new UnsupportedFlavorException(flavor);
163: }
164: }
165:
166: static class TransferAction extends AbstractAction
167: {
168: private String command;
169:
170: public TransferAction(String command)
171: {
172: super(command);
173: this.command = command;
174: }
175:
176: public void actionPerformed(ActionEvent event)
177: {
178: JComponent component = (JComponent) event.getSource();
179: TransferHandler transferHandler = component.getTransferHandler();
180: Clipboard clipboard = getClipboard(component);
181:
182: if (clipboard == null)
183: {
184:
185: Toolkit.getDefaultToolkit().beep();
186: return;
187: }
188:
189: if (command.equals(COMMAND_COPY))
190: transferHandler.exportToClipboard(component, clipboard, COPY);
191: else if (command.equals(COMMAND_CUT))
192: transferHandler.exportToClipboard(component, clipboard, MOVE);
193: else if (command.equals(COMMAND_PASTE))
194: {
195: Transferable transferable = clipboard.getContents(null);
196:
197: if (transferable != null)
198: transferHandler.importData(component, transferable);
199: }
200: }
201:
202:
209: private static Clipboard getClipboard(JComponent component)
210: {
211: try
212: {
213: return component.getToolkit().getSystemClipboard();
214: }
215: catch (SecurityException se)
216: {
217: return null;
218: }
219: }
220: }
221:
222: private static class SwingDragGestureRecognizer extends DragGestureRecognizer
223: {
224:
225: protected SwingDragGestureRecognizer(DragGestureListener dgl)
226: {
227: super(DragSource.getDefaultDragSource(), null, NONE, dgl);
228: }
229:
230: void gesture(JComponent c, MouseEvent e, int src, int drag)
231: {
232: setComponent(c);
233: setSourceActions(src);
234: appendEvent(e);
235: fireDragGestureRecognized(drag, e.getPoint());
236: }
237:
238: protected void registerListeners()
239: {
240:
241: }
242:
243: protected void unregisterListeners()
244: {
245:
246: }
247:
248: }
249:
250: private static class SwingDragHandler
251: implements DragGestureListener, DragSourceListener
252: {
253:
254: private boolean autoscrolls;
255:
256: public void dragGestureRecognized(DragGestureEvent e)
257: {
258: JComponent c = (JComponent) e.getComponent();
259: TransferHandler th = c.getTransferHandler();
260: Transferable t = th.createTransferable(c);
261: if (t != null)
262: {
263: autoscrolls = c.getAutoscrolls();
264: c.setAutoscrolls(false);
265: try
266: {
267: e.startDrag(null, t, this);
268: return;
269: }
270: finally
271: {
272: c.setAutoscrolls(autoscrolls);
273: }
274: }
275: th.exportDone(c, t, NONE);
276: }
277:
278: public void dragDropEnd(DragSourceDropEvent e)
279: {
280: DragSourceContext ctx = e.getDragSourceContext();
281: JComponent c = (JComponent) ctx.getComponent();
282: TransferHandler th = c.getTransferHandler();
283: if (e.getDropSuccess())
284: {
285: th.exportDone(c, ctx.getTransferable(), e.getDropAction());
286: }
287: else
288: {
289: th.exportDone(c, ctx.getTransferable(), e.getDropAction());
290: }
291: c.setAutoscrolls(autoscrolls);
292: }
293:
294: public void dragEnter(DragSourceDragEvent e)
295: {
296:
297: }
298:
299: public void dragExit(DragSourceEvent e)
300: {
301:
302: }
303:
304: public void dragOver(DragSourceDragEvent e)
305: {
306:
307: }
308:
309: public void dropActionChanged(DragSourceDragEvent e)
310: {
311:
312: }
313:
314: }
315:
316: private static final long serialVersionUID = -967749805571669910L;
317:
318: private static final String COMMAND_COPY = "copy";
319: private static final String COMMAND_CUT = "cut";
320: private static final String COMMAND_PASTE = "paste";
321:
322: public static final int NONE = 0;
323: public static final int COPY = 1;
324: public static final int MOVE = 2;
325: public static final int COPY_OR_MOVE = 3;
326:
327: private static Action copyAction = new TransferAction(COMMAND_COPY);
328: private static Action cutAction = new TransferAction(COMMAND_CUT);
329: private static Action pasteAction = new TransferAction(COMMAND_PASTE);
330:
331: private int sourceActions;
332: private Icon visualRepresentation;
333:
334:
338: private String propertyName;
339:
340:
343: private SwingDragGestureRecognizer recognizer;
344:
345: public static Action getCopyAction()
346: {
347: return copyAction;
348: }
349:
350: public static Action getCutAction()
351: {
352: return cutAction;
353: }
354:
355: public static Action getPasteAction()
356: {
357: return pasteAction;
358: }
359:
360: protected TransferHandler()
361: {
362: this.sourceActions = NONE;
363: }
364:
365: public TransferHandler(String property)
366: {
367: propertyName = property;
368: this.sourceActions = property != null ? COPY : NONE;
369: }
370:
371:
390: public boolean canImport(JComponent c, DataFlavor[] flavors)
391: {
392: PropertyDescriptor propDesc = getPropertyDescriptor(c);
393: boolean canImport = false;
394: if (propDesc != null)
395: {
396:
397:
398: Method writer = propDesc.getWriteMethod();
399: if (writer != null)
400: {
401: Class[] params = writer.getParameterTypes();
402: if (params.length == 1)
403: {
404:
405:
406: DataFlavor flavor = getPropertyDataFlavor(params[0], flavors);
407: if (flavor != null)
408: canImport = true;
409: }
410: }
411: }
412: return canImport;
413: }
414:
415:
429: protected Transferable createTransferable(JComponent c)
430: {
431: Transferable transferable = null;
432: if (propertyName != null)
433: {
434: PropertyDescriptor prop = getPropertyDescriptor(c);
435: if (prop != null)
436: transferable = new PropertyTransferable(c, prop);
437: }
438: return transferable;
439: }
440:
441: public void exportAsDrag(JComponent c, InputEvent e, int action)
442: {
443: int src = getSourceActions(c);
444: int drag = src & action;
445: if (! (e instanceof MouseEvent))
446: {
447: drag = NONE;
448: }
449: if (drag != NONE)
450: {
451: if (recognizer == null)
452: {
453: SwingDragHandler ds = new SwingDragHandler();
454: recognizer = new SwingDragGestureRecognizer(ds);
455: }
456: recognizer.gesture(c, (MouseEvent) e, src, drag);
457: }
458: else
459: {
460: exportDone(c, null, NONE);
461: }
462: }
463:
464:
476: protected void exportDone(JComponent c, Transferable data, int action)
477: {
478:
479: }
480:
481:
502: public void exportToClipboard(JComponent c, Clipboard clip, int action)
503: throws IllegalStateException
504: {
505: action &= getSourceActions(c);
506: Transferable transferable = createTransferable(c);
507: if (transferable != null && action != NONE)
508: {
509: try
510: {
511: clip.setContents(transferable, null);
512: exportDone(c, transferable, action);
513: }
514: catch (IllegalStateException ex)
515: {
516: exportDone(c, transferable, NONE);
517: throw ex;
518: }
519: }
520: else
521: exportDone(c, null, NONE);
522: }
523:
524: public int getSourceActions(JComponent c)
525: {
526: return sourceActions;
527: }
528:
529: public Icon getVisualRepresentation(Transferable t)
530: {
531: return visualRepresentation;
532: }
533:
534:
547: public boolean importData(JComponent c, Transferable t)
548: {
549: boolean ok = false;
550: PropertyDescriptor prop = getPropertyDescriptor(c);
551: if (prop != null)
552: {
553: Method writer = prop.getWriteMethod();
554: if (writer != null)
555: {
556: Class[] params = writer.getParameterTypes();
557: if (params.length == 1)
558: {
559: DataFlavor flavor = getPropertyDataFlavor(params[0],
560: t.getTransferDataFlavors());
561: if (flavor != null)
562: {
563: try
564: {
565: Object value = t.getTransferData(flavor);
566: writer.invoke(c, new Object[]{ value });
567: ok = true;
568: }
569: catch (Exception ex)
570: {
571:
572:
573: }
574: }
575: }
576: }
577: }
578: return ok;
579: }
580:
581:
593: private PropertyDescriptor getPropertyDescriptor(JComponent c)
594: {
595: PropertyDescriptor prop = null;
596: if (propertyName != null)
597: {
598: Class clazz = c.getClass();
599: BeanInfo beanInfo;
600: try
601: {
602: beanInfo = Introspector.getBeanInfo(clazz);
603: }
604: catch (IntrospectionException ex)
605: {
606: beanInfo = null;
607: }
608: if (beanInfo != null)
609: {
610: PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
611: for (int i = 0; i < props.length && prop == null; i++)
612: {
613: PropertyDescriptor desc = props[i];
614: if (desc.getName().equals(propertyName))
615: {
616: Method reader = desc.getReadMethod();
617: if (reader != null)
618: {
619: Class[] params = reader.getParameterTypes();
620: if (params == null || params.length == 0)
621: prop = desc;
622: }
623: }
624: }
625: }
626: }
627: return prop;
628: }
629:
630:
641: private DataFlavor getPropertyDataFlavor(Class clazz, DataFlavor[] flavors)
642: {
643: DataFlavor found = null;
644: for (int i = 0; i < flavors.length && found == null; i++)
645: {
646: DataFlavor flavor = flavors[i];
647: if (flavor.getPrimaryType().equals("application")
648: && flavor.getSubType().equals("x-java-jvm-local-objectref")
649: && clazz.isAssignableFrom(flavor.getRepresentationClass()))
650: found = flavor;
651: }
652: return found;
653: }
654: }