OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [TransferHandler.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* TransferHandler.java --
2
   Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing;
40
 
41
import java.awt.Toolkit;
42
import java.awt.datatransfer.Clipboard;
43
import java.awt.datatransfer.DataFlavor;
44
import java.awt.datatransfer.Transferable;
45
import java.awt.datatransfer.UnsupportedFlavorException;
46
import java.awt.dnd.DragGestureEvent;
47
import java.awt.dnd.DragGestureListener;
48
import java.awt.dnd.DragGestureRecognizer;
49
import java.awt.dnd.DragSource;
50
import java.awt.dnd.DragSourceContext;
51
import java.awt.dnd.DragSourceDragEvent;
52
import java.awt.dnd.DragSourceDropEvent;
53
import java.awt.dnd.DragSourceEvent;
54
import java.awt.dnd.DragSourceListener;
55
import java.awt.event.ActionEvent;
56
import java.awt.event.InputEvent;
57
import java.awt.event.MouseEvent;
58
import java.beans.BeanInfo;
59
import java.beans.IntrospectionException;
60
import java.beans.Introspector;
61
import java.beans.PropertyDescriptor;
62
import java.io.IOException;
63
import java.io.Serializable;
64
import java.lang.reflect.Method;
65
 
66
public class TransferHandler implements Serializable
67
{
68
 
69
  /**
70
   * An implementation of {@link Transferable} that can be used to export
71
   * data from a component's property.
72
   */
73
  private static class PropertyTransferable
74
    implements Transferable
75
  {
76
    /**
77
     * The component from which we export.
78
     */
79
    private JComponent component;
80
 
81
    /**
82
     * The property descriptor of the property that we handle.
83
     */
84
    private PropertyDescriptor property;
85
 
86
    /**
87
     * Creates a new PropertyTransferable.
88
     *
89
     * @param c the component from which we export
90
     * @param prop the property from which we export
91
     */
92
    PropertyTransferable(JComponent c, PropertyDescriptor prop)
93
    {
94
      component = c;
95
      property = prop;
96
    }
97
 
98
    /**
99
     * Returns the data flavors supported by the Transferable.
100
     *
101
     * @return the data flavors supported by the Transferable
102
     */
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
    /**
122
     * Returns <code>true</code> when the specified data flavor is supported,
123
     * <code>false</code> otherwise.
124
     *
125
     * @return <code>true</code> when the specified data flavor is supported,
126
     *         <code>false</code> otherwise
127
     */
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
    /**
137
     * Returns the actual transfer data.
138
     *
139
     * @param flavor the data flavor
140
     *
141
     * @return the actual transfer data
142
     */
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
          // Access denied!
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
    /**
203
     * Get the system cliboard or null if the caller isn't allowed to
204
     * access the system clipboard.
205
     *
206
     * @param component a component, used to get the toolkit.
207
     * @return the clipboard
208
     */
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
      // Nothing to do here.
241
    }
242
 
243
    protected void unregisterListeners()
244
    {
245
      // Nothing to do here.
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
      // Nothing to do here.
297
    }
298
 
299
    public void dragExit(DragSourceEvent e)
300
    {
301
      // Nothing to do here.
302
    }
303
 
304
    public void dragOver(DragSourceDragEvent e)
305
    {
306
      // Nothing to do here.
307
    }
308
 
309
    public void dropActionChanged(DragSourceDragEvent e)
310
    {
311
      // Nothing to do here.
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
  /**
335
   * The name of the property into/from which this TransferHandler
336
   * imports/exports.
337
   */
338
  private String propertyName;
339
 
340
  /**
341
   * The DragGestureRecognizer for Swing.
342
   */
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
  /**
372
   * Returns <code>true</code> if the data in this TransferHandler can be
373
   * imported into the specified component. This will be the case when:
374
   * <ul>
375
   *   <li>The component has a readable and writable property with the property
376
   *   name specified in the TransferHandler constructor.</li>
377
   *   <li>There is a dataflavor with a mime type of
378
   *     <code>application/x-java-jvm-local-object-ref</code>.</li>
379
   *   <li>The dataflavor's representation class matches the class of the
380
   *    property in the component.</li>
381
   * </li>
382
   *
383
   * @param c the component to check
384
   * @param flavors the possible data flavors
385
   *
386
   * @return <code>true</code> if the data in this TransferHandler can be
387
   *         imported into the specified component, <code>false</code>
388
   *         otherwise
389
   */
390
  public boolean canImport(JComponent c, DataFlavor[] flavors)
391
  {
392
    PropertyDescriptor propDesc = getPropertyDescriptor(c);
393
    boolean canImport = false;
394
    if (propDesc != null)
395
      {
396
        // Check if the property is writable. The readable check is already
397
        // done in getPropertyDescriptor().
398
        Method writer = propDesc.getWriteMethod();
399
        if (writer != null)
400
          {
401
            Class[] params = writer.getParameterTypes();
402
            if (params.length == 1)
403
              {
404
                // Number of parameters ok, now check mime type and
405
                // representation class.
406
                DataFlavor flavor = getPropertyDataFlavor(params[0], flavors);
407
                if (flavor != null)
408
                  canImport = true;
409
              }
410
          }
411
      }
412
    return canImport;
413
  }
414
 
415
  /**
416
   * Creates a {@link Transferable} that can be used to export data
417
   * from the specified component.
418
   *
419
   * This method returns <code>null</code> when the specified component
420
   * doesn't have a readable property that matches the property name
421
   * specified in the <code>TransferHandler</code> constructor.
422
   *
423
   * @param c the component to create a transferable for
424
   *
425
   * @return a {@link Transferable} that can be used to export data
426
   *         from the specified component, or null if the component doesn't
427
   *         have a readable property like the transfer handler
428
   */
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
  /**
465
   * This method is invoked after data has been exported.
466
   * Subclasses should implement this method to remove the data that has been
467
   * transferred when the action was <code>MOVE</code>.
468
   *
469
   * The default implementation does nothing because MOVE is not supported.
470
   *
471
   * @param c the source component
472
   * @param data the data that has been transferred or <code>null</code>
473
   *        when the action is NONE
474
   * @param action the action that has been performed
475
   */
476
  protected void exportDone(JComponent c, Transferable data, int action)
477
  {
478
    // Nothing to do in the default implementation.
479
  }
480
 
481
  /**
482
   * Exports the property of the component <code>c</code> that was
483
   * specified for this TransferHandler to the clipboard, performing
484
   * the specified action.
485
   *
486
   * This will check if the action is allowed by calling
487
   * {@link #getSourceActions(JComponent)}. If the action is not allowed,
488
   * then no export is performed.
489
   *
490
   * In either case the method {@link #exportDone} will be called with
491
   * the action that has been performed, or {@link #NONE} if the action
492
   * was not allowed or could otherwise not be completed.
493
   * Any IllegalStateException that is thrown by the Clipboard due to
494
   * beeing unavailable will be propagated through this method.
495
   *
496
   * @param c the component from which to export
497
   * @param clip the clipboard to which the data will be exported
498
   * @param action the action to perform
499
   *
500
   * @throws IllegalStateException when the clipboard is not available
501
   */
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
  /**
535
   * Imports the transfer data represented by <code>t</code> into the specified
536
   * component <code>c</code> by setting the property of this TransferHandler
537
   * on that component. If this succeeds, this method returns
538
   * <code>true</code>, otherwise <code>false</code>.
539
   *
540
   *
541
   * @param c the component to import into
542
   * @param t the transfer data to import
543
   *
544
   * @return <code>true</code> if the transfer succeeds, <code>false</code>
545
   *         otherwise
546
   */
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
                        // If anything goes wrong here, do nothing and return
572
                        // false;
573
                      }
574
                  }
575
              }
576
          }
577
      }
578
    return ok;
579
  }
580
 
581
  /**
582
   * Returns the property descriptor for the property of this TransferHandler
583
   * in the specified component, or <code>null</code> if no such property
584
   * exists in the component. This method only returns properties that are
585
   * at least readable (that is, it has a public no-arg getter method).
586
   *
587
   * @param c the component to check
588
   *
589
   * @return the property descriptor for the property of this TransferHandler
590
   *         in the specified component, or <code>null</code> if no such
591
   *         property exists in the component
592
   */
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
  /**
631
   * Searches <code>flavors</code> to find a suitable data flavor that
632
   * has the mime type application/x-java-jvm-local-objectref and a
633
   * representation class that is the same as the specified <code>clazz</code>.
634
   * When no such data flavor is found, this returns <code>null</code>.
635
   *
636
   * @param clazz the representation class required for the data flavor
637
   * @param flavors the possible data flavors
638
   *
639
   * @return the suitable data flavor or null if none is found
640
   */
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.