001    /* ImageIcon.java --
002       Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package javax.swing;
039    
040    import java.awt.Component;
041    import java.awt.Graphics;
042    import java.awt.IllegalComponentStateException;
043    import java.awt.Image;
044    import java.awt.MediaTracker;
045    import java.awt.Toolkit;
046    import java.awt.image.ImageObserver;
047    import java.io.Serializable;
048    import java.net.URL;
049    import java.util.Locale;
050    
051    import javax.accessibility.Accessible;
052    import javax.accessibility.AccessibleContext;
053    import javax.accessibility.AccessibleIcon;
054    import javax.accessibility.AccessibleRole;
055    import javax.accessibility.AccessibleStateSet;
056    
057    /**
058     * An {@link Icon} implementation that is backed by an {@link Image}.
059     */
060    public class ImageIcon
061      implements Icon, Serializable, Accessible
062    {
063      /**
064       * Provides the accessibility features for the <code>ImageIcon</code>
065       * class.
066       */
067      protected class AccessibleImageIcon
068        extends AccessibleContext
069        implements AccessibleIcon, Serializable
070      {
071        private static final long serialVersionUID = 2113430526551336564L;
072    
073        /**
074         * Creates a new instance of <code>AccessibleImageIcon</code>.
075         */
076        protected AccessibleImageIcon()
077        {
078          // Nothing to do here.
079        }
080    
081        /**
082         * Returns the accessible role for the <code>ImageIcon</code>.
083         *
084         * @return {@link AccessibleRole#ICON}.
085         */
086        public AccessibleRole getAccessibleRole()
087        {
088          return AccessibleRole.ICON;
089        }
090    
091        /**
092         * Returns the accessible state for the <code>ImageIcon</code>.  To
093         * match the reference implementation, this method always returns
094         * <code>null</code>.
095         *
096         * @return <code>null</code>.
097         */
098        public AccessibleStateSet getAccessibleStateSet()
099        {
100          // refer to Sun's bug report 4269253
101          return null;
102        }
103    
104        /**
105         * Returns the accessible parent of this object.  To match the reference
106         * implementation, this method always returns <code>null</code>.
107         *
108         * @return <code>null</code>.
109         */
110        public Accessible getAccessibleParent()
111        {
112          // refer to Sun's bug report 4269253
113          return null;
114        }
115    
116        /**
117         * Returns the index of this object in its accessible parent.  To match
118         * the reference implementation, this method always returns <code>-1</code>.
119         *
120         * @return <code>-1</code>.
121         */
122        public int getAccessibleIndexInParent()
123        {
124          // refer to Sun's bug report 4269253
125          return -1;
126        }
127    
128        /**
129         * Returns the number of accessible children of this component,
130         * which is 0, because an {@link ImageIcon} has no children.
131         *
132         * @return <code>0</code>.
133         */
134        public int getAccessibleChildrenCount()
135        {
136          return 0;
137        }
138    
139        /**
140         * Returns the accessible child at index <code>i</code>, which is
141         * <code>null</code> in this case because an {@link ImageIcon} has no
142         * children.
143         *
144         * @param i the index of the child to be fetched
145         *
146         * @return <code>null</code>.
147         */
148        public Accessible getAccessibleChild(int i)
149        {
150          return null;
151        }
152    
153        /**
154         * Returns the locale of this object.  To match the reference
155         * implementation, this method always returns <code>null</code>.
156         *
157         * @return <code>null</code>.
158         */
159        public Locale getLocale()
160          throws IllegalComponentStateException
161        {
162          // refer to Sun's bug report 4269253
163          return null;
164        }
165    
166        /**
167         * Returns the accessible icon description.  This returns the
168         * <code>description</code> property of the underlying {@link ImageIcon}.
169         *
170         * @return The description (possibly <code>null</code>).
171         *
172         * @see #setAccessibleIconDescription(String)
173         */
174        public String getAccessibleIconDescription()
175        {
176          return getDescription();
177        }
178    
179        /**
180         * Sets the accessible icon description.  This sets the
181         * <code>description</code> property of the underlying {@link ImageIcon}.
182         *
183         * @param newDescr the description (<code>null</code> permitted).
184         *
185         * @see #getAccessibleIconDescription()
186         */
187        public void setAccessibleIconDescription(String newDescr)
188        {
189          setDescription(newDescr);
190        }
191    
192        /**
193         * Returns the icon height. This returns the <code>iconHeight</code>
194         * property of the underlying {@link ImageIcon}.
195         *
196         * @return The icon height.
197         */
198        public int getAccessibleIconHeight()
199        {
200          return getIconHeight();
201        }
202    
203        /**
204         * Returns the icon width. This returns the <code>iconWidth</code> property
205         * of the underlying {@link ImageIcon}.
206         *
207         * @return The icon width.
208         */
209        public int getAccessibleIconWidth()
210        {
211          return getIconWidth();
212        }
213      } // AccessibleIcon
214    
215      private static final long serialVersionUID = 532615968316031794L;
216    
217      /** A dummy Component that is used in the MediaTracker. */
218      protected static final Component component = new Component()
219      {
220        // No need to implement this.
221      };
222    
223      /** The MediaTracker used to monitor the loading of images. */
224      protected static final MediaTracker tracker = new MediaTracker(component);
225    
226      /** The ID that is used in the tracker. */
227      private static int id;
228    
229      Image image;
230      String description;
231      ImageObserver observer;
232    
233      /** The image loading status. */
234      private int loadStatus;
235    
236      /** The AccessibleContext of this ImageIcon. */
237      private AccessibleContext accessibleContext;
238    
239      /**
240       * Creates an ImageIcon without any properties set.
241       */
242      public ImageIcon()
243      {
244        // Nothing to do here.
245      }
246    
247      /**
248       * Constructs an ImageIcon given a filename.  The icon's description
249       * is initially set to the filename itself.  A filename of "" means
250       * create a blank icon.
251       *
252       * @param filename name of file to load or "" for a blank icon
253       */
254      public ImageIcon(String filename)
255      {
256        this(filename, filename);
257      }
258    
259      /**
260       * Constructs an ImageIcon from the given filename, setting its
261       * description to the given description.  A filename of "" means
262       * create a blank icon.
263       *
264       * @param filename name of file to load or "" for a blank icon
265       * @param description human-readable description of this icon
266       */
267      public ImageIcon(String filename, String description)
268      {
269        this(Toolkit.getDefaultToolkit().getImage(filename), description);
270      }
271    
272      /**
273       * Creates an ImageIcon from the given byte array without any
274       * description set.
275       */
276      public ImageIcon(byte[] imageData)
277      {
278        this(imageData, null);
279      }
280    
281      /**
282       * Creates an ImageIcon from the given byte array and sets the given
283       * description.
284       */
285      public ImageIcon(byte[] imageData, String description)
286      {
287        this(Toolkit.getDefaultToolkit().createImage(imageData), description);
288      }
289    
290      /**
291       * Creates an ImageIcon from the given URL and sets the description
292       * to the URL String representation.
293       */
294      public ImageIcon(URL url)
295      {
296        this(url, url.toString());
297      }
298    
299      /**
300       * Creates an ImageIcon from the given URL and sets the given
301       * description.
302       */
303      public ImageIcon(URL url, String description)
304      {
305        this(Toolkit.getDefaultToolkit().getImage(url), description);
306      }
307    
308      /**
309       * Creates an ImageIcon from the given Image without any description
310       * set.
311       */
312      public ImageIcon(Image image)
313      {
314        this(image, null);
315      }
316    
317      /**
318       * Creates an ImageIcon from the given Image and sets the given
319       * description.
320       */
321      public ImageIcon(Image image, String description)
322      {
323        setImage(image);
324        setDescription(description);
325      }
326    
327      /**
328       * Returns the ImageObserver that is used for all Image
329       * operations. Defaults to null when not explicitly set.
330       */
331      public ImageObserver getImageObserver()
332      {
333        return observer;
334      }
335    
336      /**
337       * Sets the ImageObserver that will be used for all Image
338       * operations. Can be set to null (the default) when no observer is
339       * needed.
340       */
341      public void setImageObserver(ImageObserver newObserver)
342      {
343        observer = newObserver;
344      }
345    
346      /**
347       * Returns the backing Image for this ImageIcon. Might be set to
348       * null in which case no image is shown.
349       */
350      public Image getImage()
351      {
352        return image;
353      }
354    
355      /**
356       * Explicitly sets the backing Image for this ImageIcon. Will call
357       * loadImage() to make sure that the Image is completely loaded
358       * before returning.
359       */
360      public void setImage(Image image)
361      {
362        loadImage(image);
363        this.image = image;
364      }
365    
366      /**
367       * Returns a human readable description for this ImageIcon or null
368       * when no description is set or available.
369       */
370      public String getDescription()
371      {
372        return description;
373      }
374    
375      /**
376       * Sets a human readable description for this ImageIcon. Can be set
377       * to null when no description is available.
378       */
379      public void setDescription(String description)
380      {
381        this.description = description;
382      }
383    
384      /**
385       * Returns the the height of the backing Image, or -1 if the backing
386       * Image is null. The getHeight() method of the Image will be called
387       * with the set observer of this ImageIcon.
388       */
389      public int getIconHeight()
390      {
391        if (image == null)
392          return -1;
393    
394        return image.getHeight(observer);
395      }
396    
397      /**
398       * Returns the the width of the backing Image, or -1 if the backing
399       * Image is null. The getWidth() method of the Image will be called
400       * with the set observer of this ImageIcon.
401       */
402      public int getIconWidth()
403      {
404        if (image == null)
405          return -1;
406    
407        return image.getWidth(observer);
408      }
409    
410      /**
411       * Calls <code>g.drawImage()</code> on the backing Image using the
412       * set observer of this ImageIcon. If the set observer is null, the
413       * given Component is used as observer.
414       */
415      public void paintIcon(Component c, Graphics g, int x, int y)
416      {
417        g.drawImage(image, x, y, observer != null ? observer : c);
418      }
419    
420      /**
421       * Loads the image and blocks until the loading operation is finished.
422       *
423       * @param image the image to be loaded
424       */
425      protected void loadImage(Image image)
426      {
427        try
428          {
429            tracker.addImage(image, id);
430            id++;
431            tracker.waitForID(id - 1);
432          }
433        catch (InterruptedException ex)
434          {
435            // Ignore this for now.
436          }
437        finally
438          {
439            loadStatus = tracker.statusID(id - 1, false);
440            tracker.removeImage(image, id - 1);
441          }
442      }
443    
444      /**
445       * Returns the load status of the icon image.
446       *
447       * @return the load status of the icon image
448       *
449       * @see MediaTracker#COMPLETE
450       * @see MediaTracker#ABORTED
451       * @see MediaTracker#ERRORED
452       */
453      public int getImageLoadStatus()
454      {
455        return loadStatus;
456      }
457    
458      /**
459       * Returns the object that provides accessibility features for this
460       * <code>ImageIcon</code> instance.
461       *
462       * @return The accessible context (an instance of
463       *     {@link AccessibleImageIcon}).
464       */
465      public AccessibleContext getAccessibleContext()
466      {
467        if (accessibleContext == null)
468          accessibleContext = new AccessibleImageIcon();
469        return accessibleContext;
470      }
471    }