Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / gnu / java / awt / peer / gtk / GtkSelection.java
blob08b6b66dd1f877828105105193c7e3d72bc6e343
1 /* GtkClipboard.java - Class representing gtk+ clipboard selection.
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package gnu.java.awt.peer.gtk;
41 import gnu.classpath.Pointer;
43 import java.awt.datatransfer.*;
45 import java.io.*;
46 import java.net.*;
47 import java.util.*;
49 import java.awt.Image;
51 /**
52 * Class representing the gtk+ clipboard selection. This is used when
53 * another program owns the clipboard. Whenever the system clipboard
54 * selection changes we create a new instance to notify the program
55 * that the available flavors might have changed. When requested it
56 * (lazily) caches the targets, and (text, image, or files/uris)
57 * clipboard contents.
59 * XXX - should only cache when
60 * gdk_display_supports_selection_notification is true.
62 public class GtkSelection implements Transferable
64 /**
65 * Static lock used for requests of mimetypes and contents retrieval.
67 static private Object requestLock = new Object();
69 /**
70 * Whether a request for mimetypes, text, images, uris or byte[] is
71 * currently in progress. Should only be tested or set with
72 * requestLock held. When true no other requests should be made till
73 * it is false again.
75 private boolean requestInProgress;
77 /**
78 * Indicates a requestMimeTypes() call was made and the
79 * corresponding mimeTypesAvailable() callback was triggered.
81 private boolean mimeTypesDelivered;
83 /**
84 * Set and returned by getTransferDataFlavors. Only valid when
85 * mimeTypesDelivered is true.
87 private DataFlavor[] dataFlavors;
89 /**
90 * Indicates a requestText() call was made and the corresponding
91 * textAvailable() callback was triggered.
93 private boolean textDelivered;
95 /**
96 * Set as response to a requestText() call and possibly returned by
97 * getTransferData() for text targets. Only valid when textDelivered
98 * is true.
100 private String text;
103 * Indicates a requestImage() call was made and the corresponding
104 * imageAvailable() callback was triggered.
106 private boolean imageDelivered;
109 * Set as response to a requestImage() call and possibly returned by
110 * getTransferData() for image targets. Only valid when
111 * imageDelivered is true and image is null.
113 private Pointer imagePointer;
116 * Cached image value. Only valid when imageDelivered is
117 * true. Created from imagePointer.
119 private Image image;
122 * Indicates a requestUris() call was made and the corresponding
123 * urisAvailable() callback was triggered.
125 private boolean urisDelivered;
128 * Set as response to a requestURIs() call. Only valid when
129 * urisDelivered is true
131 private List uris;
134 * Indicates a requestBytes(String) call was made and the
135 * corresponding bytesAvailable() callback was triggered.
137 private boolean bytesDelivered;
140 * Set as response to a requestBytes(String) call. Only valid when
141 * bytesDelivered is true.
143 private byte[] bytes;
146 * Should only be created by the GtkClipboard class.
148 GtkSelection()
153 * Gets an array of mime-type strings from the gtk+ clipboard and
154 * transforms them into an array of DataFlavors.
156 public DataFlavor[] getTransferDataFlavors()
158 DataFlavor[] result;
159 synchronized (requestLock)
161 // Did we request already and cache the result?
162 if (mimeTypesDelivered)
163 result = (DataFlavor[]) dataFlavors.clone();
164 else
166 // Wait till there are no pending requests.
167 while (requestInProgress)
171 requestLock.wait();
173 catch (InterruptedException ie)
175 // ignored
179 // If nobody else beat us and cached the result we try
180 // ourselves to get it.
181 if (! mimeTypesDelivered)
183 requestInProgress = true;
184 requestMimeTypes();
185 while (! mimeTypesDelivered)
189 requestLock.wait();
191 catch (InterruptedException ie)
193 // ignored
196 requestInProgress = false;
198 result = dataFlavors;
199 if (! GtkClipboard.canCache)
201 dataFlavors = null;
202 mimeTypesDelivered = false;
204 requestLock.notifyAll();
207 return result;
211 * Callback that sets the available DataFlavors[]. Note that this
212 * should not call any code that could need the main gdk lock.
214 private void mimeTypesAvailable(String[] mimeTypes)
216 synchronized (requestLock)
218 if (mimeTypes == null)
219 dataFlavors = new DataFlavor[0];
220 else
222 // Most likely the mimeTypes include text in which case we add an
223 // extra element.
224 ArrayList flavorsList = new ArrayList(mimeTypes.length + 1);
225 for (int i = 0; i < mimeTypes.length; i++)
229 if (mimeTypes[i] == GtkClipboard.stringMimeType)
231 // XXX - Fix DataFlavor.getTextPlainUnicodeFlavor()
232 // and also add it to the list.
233 flavorsList.add(DataFlavor.stringFlavor);
234 flavorsList.add(DataFlavor.plainTextFlavor);
236 else if (mimeTypes[i] == GtkClipboard.imageMimeType)
237 flavorsList.add(DataFlavor.imageFlavor);
238 else if (mimeTypes[i] == GtkClipboard.filesMimeType)
239 flavorsList.add(DataFlavor.javaFileListFlavor);
240 else
242 // We check the target to prevent duplicates
243 // of the "magic" targets above.
244 DataFlavor target = new DataFlavor(mimeTypes[i]);
245 if (! flavorsList.contains(target))
246 flavorsList.add(target);
249 catch (ClassNotFoundException cnfe)
251 cnfe.printStackTrace();
253 catch (NullPointerException npe)
255 npe.printStackTrace();
259 dataFlavors = new DataFlavor[flavorsList.size()];
260 flavorsList.toArray(dataFlavors);
263 mimeTypesDelivered = true;
264 requestLock.notifyAll();
269 * Gets the available data flavors for this selection and checks
270 * that at least one of them is equal to the given DataFlavor.
272 public boolean isDataFlavorSupported(DataFlavor flavor)
274 DataFlavor[] dfs = getTransferDataFlavors();
275 for (int i = 0; i < dfs.length; i++)
276 if (flavor.equals(dfs[i]))
277 return true;
279 return false;
283 * Helper method that tests whether we already have the text for the
284 * current gtk+ selection on the clipboard and if not requests it
285 * and waits till it is available.
287 private String getText()
289 String result;
290 synchronized (requestLock)
292 // Did we request already and cache the result?
293 if (textDelivered)
294 result = text;
295 else
297 // Wait till there are no pending requests.
298 while (requestInProgress)
302 requestLock.wait();
304 catch (InterruptedException ie)
306 // ignored
310 // If nobody else beat us we try ourselves to get and
311 // caching the result.
312 if (! textDelivered)
314 requestInProgress = true;
315 requestText();
316 while (! textDelivered)
320 requestLock.wait();
322 catch (InterruptedException ie)
324 // ignored
327 requestInProgress = false;
329 result = text;
330 if (! GtkClipboard.canCache)
332 text = null;
333 textDelivered = false;
335 requestLock.notifyAll();
338 return result;
342 * Callback that sets the available text on the clipboard. Note that
343 * this should not call any code that could need the main gdk lock.
345 private void textAvailable(String text)
347 synchronized (requestLock)
349 this.text = text;
350 textDelivered = true;
351 requestLock.notifyAll();
356 * Helper method that tests whether we already have an image for the
357 * current gtk+ selection on the clipboard and if not requests it
358 * and waits till it is available.
360 private Image getImage()
362 Image result;
363 synchronized (requestLock)
365 // Did we request already and cache the result?
366 if (imageDelivered)
367 result = image;
368 else
370 // Wait till there are no pending requests.
371 while (requestInProgress)
375 requestLock.wait();
377 catch (InterruptedException ie)
379 // ignored
383 // If nobody else beat us we try ourselves to get and
384 // caching the result.
385 if (! imageDelivered)
387 requestInProgress = true;
388 requestImage();
389 while (! imageDelivered)
393 requestLock.wait();
395 catch (InterruptedException ie)
397 // ignored
400 requestInProgress = false;
402 if (imagePointer != null)
403 image = new GtkImage(imagePointer);
404 imagePointer = null;
405 result = image;
406 if (! GtkClipboard.canCache)
408 image = null;
409 imageDelivered = false;
411 requestLock.notifyAll();
414 return result;
418 * Callback that sets the available image on the clipboard. Note
419 * that this should not call any code that could need the main gdk
420 * lock. Note that we get a Pointer to a GdkPixbuf which we cannot
421 * turn into a real GtkImage at this point. That will be done on the
422 * "user thread" in getImage().
424 private void imageAvailable(Pointer pointer)
426 synchronized (requestLock)
428 this.imagePointer = pointer;
429 imageDelivered = true;
430 requestLock.notifyAll();
435 * Helper method that test whether we already have a list of
436 * URIs/Files and if not requests them and waits till they are
437 * available.
439 private List getURIs()
441 List result;
442 synchronized (requestLock)
444 // Did we request already and cache the result?
445 if (urisDelivered)
446 result = uris;
447 else
449 // Wait till there are no pending requests.
450 while (requestInProgress)
454 requestLock.wait();
456 catch (InterruptedException ie)
458 // ignored
462 // If nobody else beat us we try ourselves to get and
463 // caching the result.
464 if (! urisDelivered)
466 requestInProgress = true;
467 requestURIs();
468 while (! urisDelivered)
472 requestLock.wait();
474 catch (InterruptedException ie)
476 // ignored
479 requestInProgress = false;
481 result = uris;
482 if (! GtkClipboard.canCache)
484 uris = null;
485 urisDelivered = false;
487 requestLock.notifyAll();
490 return result;
494 * Callback that sets the available File list. Note that this should
495 * not call any code that could need the main gdk lock.
497 private void urisAvailable(String[] uris)
499 synchronized (requestLock)
501 if (uris != null && uris.length != 0)
503 ArrayList list = new ArrayList(uris.length);
504 for (int i = 0; i < uris.length; i++)
508 URI uri = new URI(uris[i]);
509 if (uri.getScheme().equals("file"))
510 list.add(new File(uri));
512 catch (URISyntaxException use)
516 this.uris = list;
519 urisDelivered = true;
520 requestLock.notifyAll();
525 * Helper method that requests a byte[] for the given target
526 * mime-type flavor and waits till it is available. Note that unlike
527 * the other get methods this one doesn't cache the result since
528 * there are possibly many targets.
530 private byte[] getBytes(String target)
532 byte[] result;
533 synchronized (requestLock)
535 // Wait till there are no pending requests.
536 while (requestInProgress)
540 requestLock.wait();
542 catch (InterruptedException ie)
544 // ignored
548 // Request bytes and wait till they are available.
549 requestInProgress = true;
550 requestBytes(target);
551 while (! bytesDelivered)
555 requestLock.wait();
557 catch (InterruptedException ie)
559 // ignored
562 result = bytes;
563 bytes = null;
564 bytesDelivered = false;
565 requestInProgress = false;
567 requestLock.notifyAll();
569 return result;
573 * Callback that sets the available byte array on the
574 * clipboard. Note that this should not call any code that could
575 * need the main gdk lock.
577 private void bytesAvailable(byte[] bytes)
579 synchronized (requestLock)
581 this.bytes = bytes;
582 bytesDelivered = true;
583 requestLock.notifyAll();
587 public Object getTransferData(DataFlavor flavor)
588 throws UnsupportedFlavorException
590 // Note the fall throughs for the "magic targets" if they fail we
591 // try one more time through getBytes().
592 if (flavor.equals(DataFlavor.stringFlavor))
594 String text = getText();
595 if (text != null)
596 return text;
599 if (flavor.equals(DataFlavor.plainTextFlavor))
601 String text = getText();
602 if (text != null)
603 return new StringBufferInputStream(text);
606 if (flavor.equals(DataFlavor.imageFlavor))
608 Image image = getImage();
609 if (image != null)
610 return image;
613 if (flavor.equals(DataFlavor.javaFileListFlavor))
615 List uris = getURIs();
616 if (uris != null)
617 return uris;
620 byte[] bytes = getBytes(flavor.getMimeType());
621 if (bytes == null)
622 throw new UnsupportedFlavorException(flavor);
624 if (flavor.isMimeTypeSerializedObject())
628 ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
629 ObjectInputStream ois = new ObjectInputStream(bais);
630 return ois.readObject();
632 catch (IOException ioe)
634 ioe.printStackTrace();
636 catch (ClassNotFoundException cnfe)
638 cnfe.printStackTrace();
642 if (flavor.isRepresentationClassInputStream())
643 return new ByteArrayInputStream(bytes);
645 // XXX, need some more conversions?
647 throw new UnsupportedFlavorException(flavor);
651 * Requests text, Image or an byte[] for a particular target from the
652 * other application. These methods return immediately. When the
653 * content is available the contentLock will be notified through
654 * textAvailable, imageAvailable, urisAvailable or bytesAvailable and the
655 * appropriate field is set.
657 private native void requestText();
658 private native void requestImage();
659 private native void requestURIs();
660 private native void requestBytes(String target);
662 /* Similar to the above but for requesting the supported targets. */
663 private native void requestMimeTypes();