64 implements PropertyChangeListener {
65
66 public static final FlavorTable flavorMap =
67 (FlavorTable)SystemFlavorMap.getDefaultFlavorMap();
68
69 private AppContext contentsContext = null;
70
71 private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;
72
73 /**
74 * A number of <code>FlavorListener</code>s currently registered
75 * on this clipboard across all <code>AppContext</code>s.
76 */
77 private volatile int numberOfFlavorListeners = 0;
78
79 /**
80 * A set of <code>DataFlavor</code>s that is available on
81 * this clipboard. It is used for tracking changes
82 * of <code>DataFlavor</code>s available on this clipboard.
83 */
84 private volatile Set currentDataFlavors;
85
86
87 public SunClipboard(String name) {
88 super(name);
89 CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY");
90 }
91
92 public synchronized void setContents(Transferable contents,
93 ClipboardOwner owner) {
94 // 4378007 : Toolkit.getSystemClipboard().setContents(null, null)
95 // should throw NPE
96 if (contents == null) {
97 throw new NullPointerException("contents");
98 }
99
100 initContext();
101
102 final ClipboardOwner oldOwner = this.owner;
103 final Transferable oldContents = this.contents;
104
324 */
325 protected long[] getClipboardFormatsOpenClose() {
326 try {
327 openClipboard(null);
328 return getClipboardFormats();
329 } finally {
330 closeClipboard();
331 }
332 }
333
334 /**
335 * Returns zero-length array (not null) if the number of available formats is zero.
336 *
337 * @throws IllegalStateException if formats could not be retrieved
338 */
339 protected abstract long[] getClipboardFormats();
340
341 protected abstract byte[] getClipboardData(long format) throws IOException;
342
343
344 private static Set formatArrayAsDataFlavorSet(long[] formats) {
345 return (formats == null) ? null :
346 DataTransferer.getInstance().
347 getFlavorsForFormatsAsSet(formats, flavorMap);
348 }
349
350
351 public synchronized void addFlavorListener(FlavorListener listener) {
352 if (listener == null) {
353 return;
354 }
355 AppContext appContext = AppContext.getAppContext();
356 Set<FlavorListener> flavorListeners = getFlavorListeners(appContext);
357 if (flavorListeners == null) {
358 flavorListeners = new HashSet<>();
359 appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, flavorListeners);
360 }
361 flavorListeners.add(listener);
362
363 if (numberOfFlavorListeners++ == 0) {
364 long[] currentFormats = null;
403
404 public boolean areFlavorListenersRegistered() {
405 return (numberOfFlavorListeners > 0);
406 }
407
408 protected abstract void registerClipboardViewerChecked();
409
410 protected abstract void unregisterClipboardViewerChecked();
411
412 /**
413 * Checks change of the <code>DataFlavor</code>s and, if necessary,
414 * posts notifications on <code>FlavorEvent</code>s to the
415 * AppContexts' EDTs.
416 * The parameter <code>formats</code> is null iff we have just
417 * failed to get formats available on the clipboard.
418 *
419 * @param formats data formats that have just been retrieved from
420 * this clipboard
421 */
422 public void checkChange(long[] formats) {
423 Set prevDataFlavors = currentDataFlavors;
424 currentDataFlavors = formatArrayAsDataFlavorSet(formats);
425
426 if (Objects.equals(prevDataFlavors, currentDataFlavors)) {
427 // we've been able to successfully get available on the clipboard
428 // DataFlavors this and previous time and they are coincident;
429 // don't notify
430 return;
431 }
432
433 for (AppContext appContext : AppContext.getAppContexts()) {
434 if (appContext == null || appContext.isDisposed()) {
435 continue;
436 }
437 Set<FlavorListener> flavorListeners = getFlavorListeners(appContext);
438 if (flavorListeners != null) {
439 for (FlavorListener listener : flavorListeners) {
440 if (listener != null) {
441 PeerEvent peerEvent = new PeerEvent(this,
442 () -> listener.flavorsChanged(new FlavorEvent(SunClipboard.this)),
443 PeerEvent.PRIORITY_EVENT);
|
64 implements PropertyChangeListener {
65
66 public static final FlavorTable flavorMap =
67 (FlavorTable)SystemFlavorMap.getDefaultFlavorMap();
68
69 private AppContext contentsContext = null;
70
71 private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;
72
73 /**
74 * A number of <code>FlavorListener</code>s currently registered
75 * on this clipboard across all <code>AppContext</code>s.
76 */
77 private volatile int numberOfFlavorListeners = 0;
78
79 /**
80 * A set of <code>DataFlavor</code>s that is available on
81 * this clipboard. It is used for tracking changes
82 * of <code>DataFlavor</code>s available on this clipboard.
83 */
84 private volatile Set<DataFlavor> currentDataFlavors;
85
86
87 public SunClipboard(String name) {
88 super(name);
89 CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY");
90 }
91
92 public synchronized void setContents(Transferable contents,
93 ClipboardOwner owner) {
94 // 4378007 : Toolkit.getSystemClipboard().setContents(null, null)
95 // should throw NPE
96 if (contents == null) {
97 throw new NullPointerException("contents");
98 }
99
100 initContext();
101
102 final ClipboardOwner oldOwner = this.owner;
103 final Transferable oldContents = this.contents;
104
324 */
325 protected long[] getClipboardFormatsOpenClose() {
326 try {
327 openClipboard(null);
328 return getClipboardFormats();
329 } finally {
330 closeClipboard();
331 }
332 }
333
334 /**
335 * Returns zero-length array (not null) if the number of available formats is zero.
336 *
337 * @throws IllegalStateException if formats could not be retrieved
338 */
339 protected abstract long[] getClipboardFormats();
340
341 protected abstract byte[] getClipboardData(long format) throws IOException;
342
343
344 private static Set<DataFlavor> formatArrayAsDataFlavorSet(long[] formats) {
345 return (formats == null) ? null :
346 DataTransferer.getInstance().
347 getFlavorsForFormatsAsSet(formats, flavorMap);
348 }
349
350
351 public synchronized void addFlavorListener(FlavorListener listener) {
352 if (listener == null) {
353 return;
354 }
355 AppContext appContext = AppContext.getAppContext();
356 Set<FlavorListener> flavorListeners = getFlavorListeners(appContext);
357 if (flavorListeners == null) {
358 flavorListeners = new HashSet<>();
359 appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, flavorListeners);
360 }
361 flavorListeners.add(listener);
362
363 if (numberOfFlavorListeners++ == 0) {
364 long[] currentFormats = null;
403
404 public boolean areFlavorListenersRegistered() {
405 return (numberOfFlavorListeners > 0);
406 }
407
408 protected abstract void registerClipboardViewerChecked();
409
410 protected abstract void unregisterClipboardViewerChecked();
411
412 /**
413 * Checks change of the <code>DataFlavor</code>s and, if necessary,
414 * posts notifications on <code>FlavorEvent</code>s to the
415 * AppContexts' EDTs.
416 * The parameter <code>formats</code> is null iff we have just
417 * failed to get formats available on the clipboard.
418 *
419 * @param formats data formats that have just been retrieved from
420 * this clipboard
421 */
422 public void checkChange(long[] formats) {
423 Set<DataFlavor> prevDataFlavors = currentDataFlavors;
424 currentDataFlavors = formatArrayAsDataFlavorSet(formats);
425
426 if (Objects.equals(prevDataFlavors, currentDataFlavors)) {
427 // we've been able to successfully get available on the clipboard
428 // DataFlavors this and previous time and they are coincident;
429 // don't notify
430 return;
431 }
432
433 for (AppContext appContext : AppContext.getAppContexts()) {
434 if (appContext == null || appContext.isDisposed()) {
435 continue;
436 }
437 Set<FlavorListener> flavorListeners = getFlavorListeners(appContext);
438 if (flavorListeners != null) {
439 for (FlavorListener listener : flavorListeners) {
440 if (listener != null) {
441 PeerEvent peerEvent = new PeerEvent(this,
442 () -> listener.flavorsChanged(new FlavorEvent(SunClipboard.this)),
443 PeerEvent.PRIORITY_EVENT);
|