001/* ImageIcon.java --
002   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package javax.swing;
039
040import java.awt.Component;
041import java.awt.Graphics;
042import java.awt.IllegalComponentStateException;
043import java.awt.Image;
044import java.awt.MediaTracker;
045import java.awt.Toolkit;
046import java.awt.image.ImageObserver;
047import java.io.Serializable;
048import java.net.URL;
049import java.util.Locale;
050
051import javax.accessibility.Accessible;
052import javax.accessibility.AccessibleContext;
053import javax.accessibility.AccessibleIcon;
054import javax.accessibility.AccessibleRole;
055import javax.accessibility.AccessibleStateSet;
056
057/**
058 * An {@link Icon} implementation that is backed by an {@link Image}.
059 */
060public 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}