001 /*
002 * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package javax.swing;
026
027 import java.awt.*;
028 import java.awt.image.*;
029 import java.beans.ConstructorProperties;
030 import java.net.URL;
031
032 import java.io.Serializable;
033 import java.io.ObjectOutputStream;
034 import java.io.ObjectInputStream;
035 import java.io.IOException;
036
037 import java.util.Locale;
038 import javax.accessibility.*;
039
040 /**
041 * An implementation of the Icon interface that paints Icons
042 * from Images. Images that are created from a URL, filename or byte array
043 * are preloaded using MediaTracker to monitor the loaded state
044 * of the image.
045 *
046 * <p>
047 * For further information and examples of using image icons, see
048 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/icon.html">How to Use Icons</a>
049 * in <em>The Java Tutorial.</em>
050 *
051 * <p>
052 * <strong>Warning:</strong>
053 * Serialized objects of this class will not be compatible with
054 * future Swing releases. The current serialization support is
055 * appropriate for short term storage or RMI between applications running
056 * the same version of Swing. As of 1.4, support for long term storage
057 * of all JavaBeans<sup><font size="-2">TM</font></sup>
058 * has been added to the <code>java.beans</code> package.
059 * Please see {@link java.beans.XMLEncoder}.
060 *
061 * @version 1.60 05/05/07
062 * @author Jeff Dinkins
063 * @author Lynn Monsanto
064 */
065 public class ImageIcon implements Icon, Serializable, Accessible {
066 /* Keep references to the filename and location so that
067 * alternate persistence schemes have the option to archive
068 * images symbolically rather than including the image data
069 * in the archive.
070 */
071 transient private String filename;
072 transient private URL location;
073
074 transient Image image;
075 transient int loadStatus = 0;
076 ImageObserver imageObserver;
077 String description = null;
078
079 protected final static Component component = new Component() {
080 };
081 protected final static MediaTracker tracker = new MediaTracker(
082 component);
083
084 /**
085 * Id used in loading images from MediaTracker.
086 */
087 private static int mediaTrackerID;
088
089 int width = -1;
090 int height = -1;
091
092 /**
093 * Creates an ImageIcon from the specified file. The image will
094 * be preloaded by using MediaTracker to monitor the loading state
095 * of the image.
096 * @param filename the name of the file containing the image
097 * @param description a brief textual description of the image
098 * @see #ImageIcon(String)
099 */
100 public ImageIcon(String filename, String description) {
101 image = Toolkit.getDefaultToolkit().getImage(filename);
102 if (image == null) {
103 return;
104 }
105 this .filename = filename;
106 this .description = description;
107 loadImage(image);
108 }
109
110 /**
111 * Creates an ImageIcon from the specified file. The image will
112 * be preloaded by using MediaTracker to monitor the loading state
113 * of the image. The specified String can be a file name or a
114 * file path. When specifying a path, use the Internet-standard
115 * forward-slash ("/") as a separator.
116 * (The string is converted to an URL, so the forward-slash works
117 * on all systems.)
118 * For example, specify:
119 * <pre>
120 * new ImageIcon("images/myImage.gif") </pre>
121 * The description is initialized to the <code>filename</code> string.
122 *
123 * @param filename a String specifying a filename or path
124 * @see #getDescription
125 */
126 @ConstructorProperties({"description"})
127 public ImageIcon(String filename) {
128 this (filename, filename);
129 }
130
131 /**
132 * Creates an ImageIcon from the specified URL. The image will
133 * be preloaded by using MediaTracker to monitor the loaded state
134 * of the image.
135 * @param location the URL for the image
136 * @param description a brief textual description of the image
137 * @see #ImageIcon(String)
138 */
139 public ImageIcon(URL location, String description) {
140 image = Toolkit.getDefaultToolkit().getImage(location);
141 if (image == null) {
142 return;
143 }
144 this .location = location;
145 this .description = description;
146 loadImage(image);
147 }
148
149 /**
150 * Creates an ImageIcon from the specified URL. The image will
151 * be preloaded by using MediaTracker to monitor the loaded state
152 * of the image.
153 * The icon's description is initialized to be
154 * a string representation of the URL.
155 * @param location the URL for the image
156 * @see #getDescription
157 */
158 public ImageIcon(URL location) {
159 this (location, location.toExternalForm());
160 }
161
162 /**
163 * Creates an ImageIcon from the image.
164 * @param image the image
165 * @param description a brief textual description of the image
166 */
167 public ImageIcon(Image image, String description) {
168 this (image);
169 this .description = description;
170 }
171
172 /**
173 * Creates an ImageIcon from an image object.
174 * If the image has a "comment" property that is a string,
175 * then the string is used as the description of this icon.
176 * @param image the image
177 * @see #getDescription
178 * @see java.awt.Image#getProperty
179 */
180 public ImageIcon(Image image) {
181 this .image = image;
182 Object o = image.getProperty("comment", imageObserver);
183 if (o instanceof String) {
184 description = (String) o;
185 }
186 loadImage(image);
187 }
188
189 /**
190 * Creates an ImageIcon from an array of bytes which were
191 * read from an image file containing a supported image format,
192 * such as GIF, JPEG, or (as of 1.3) PNG.
193 * Normally this array is created
194 * by reading an image using Class.getResourceAsStream(), but
195 * the byte array may also be statically stored in a class.
196 *
197 * @param imageData an array of pixels in an image format supported
198 * by the AWT Toolkit, such as GIF, JPEG, or (as of 1.3) PNG
199 * @param description a brief textual description of the image
200 * @see java.awt.Toolkit#createImage
201 */
202 public ImageIcon(byte[] imageData, String description) {
203 this .image = Toolkit.getDefaultToolkit().createImage(imageData);
204 if (image == null) {
205 return;
206 }
207 this .description = description;
208 loadImage(image);
209 }
210
211 /**
212 * Creates an ImageIcon from an array of bytes which were
213 * read from an image file containing a supported image format,
214 * such as GIF, JPEG, or (as of 1.3) PNG.
215 * Normally this array is created
216 * by reading an image using Class.getResourceAsStream(), but
217 * the byte array may also be statically stored in a class.
218 * If the resulting image has a "comment" property that is a string,
219 * then the string is used as the description of this icon.
220 *
221 * @param imageData an array of pixels in an image format supported by
222 * the AWT Toolkit, such as GIF, JPEG, or (as of 1.3) PNG
223 * @see java.awt.Toolkit#createImage
224 * @see #getDescription
225 * @see java.awt.Image#getProperty
226 */
227 public ImageIcon(byte[] imageData) {
228 this .image = Toolkit.getDefaultToolkit().createImage(imageData);
229 if (image == null) {
230 return;
231 }
232 Object o = image.getProperty("comment", imageObserver);
233 if (o instanceof String) {
234 description = (String) o;
235 }
236 loadImage(image);
237 }
238
239 /**
240 * Creates an uninitialized image icon.
241 */
242 public ImageIcon() {
243 }
244
245 /**
246 * Loads the image, returning only when the image is loaded.
247 * @param image the image
248 */
249 protected void loadImage(Image image) {
250 synchronized (tracker) {
251 int id = getNextID();
252
253 tracker.addImage(image, id);
254 try {
255 tracker.waitForID(id, 0);
256 } catch (InterruptedException e) {
257 System.out.println("INTERRUPTED while loading Image");
258 }
259 loadStatus = tracker.statusID(id, false);
260 tracker.removeImage(image, id);
261
262 width = image.getWidth(imageObserver);
263 height = image.getHeight(imageObserver);
264 }
265 }
266
267 /**
268 * Returns an ID to use with the MediaTracker in loading an image.
269 */
270 private int getNextID() {
271 synchronized (tracker) {
272 return ++mediaTrackerID;
273 }
274 }
275
276 /**
277 * Returns the status of the image loading operation.
278 * @return the loading status as defined by java.awt.MediaTracker
279 * @see java.awt.MediaTracker#ABORTED
280 * @see java.awt.MediaTracker#ERRORED
281 * @see java.awt.MediaTracker#COMPLETE
282 */
283 public int getImageLoadStatus() {
284 return loadStatus;
285 }
286
287 /**
288 * Returns this icon's <code>Image</code>.
289 * @return the <code>Image</code> object for this <code>ImageIcon</code>
290 */
291 public Image getImage() {
292 return image;
293 }
294
295 /**
296 * Sets the image displayed by this icon.
297 * @param image the image
298 */
299 public void setImage(Image image) {
300 this .image = image;
301 loadImage(image);
302 }
303
304 /**
305 * Gets the description of the image. This is meant to be a brief
306 * textual description of the object. For example, it might be
307 * presented to a blind user to give an indication of the purpose
308 * of the image.
309 * The description may be null.
310 *
311 * @return a brief textual description of the image
312 */
313 public String getDescription() {
314 return description;
315 }
316
317 /**
318 * Sets the description of the image. This is meant to be a brief
319 * textual description of the object. For example, it might be
320 * presented to a blind user to give an indication of the purpose
321 * of the image.
322 * @param description a brief textual description of the image
323 */
324 public void setDescription(String description) {
325 this .description = description;
326 }
327
328 /**
329 * Paints the icon.
330 * The top-left corner of the icon is drawn at
331 * the point (<code>x</code>, <code>y</code>)
332 * in the coordinate space of the graphics context <code>g</code>.
333 * If this icon has no image observer,
334 * this method uses the <code>c</code> component
335 * as the observer.
336 *
337 * @param c the component to be used as the observer
338 * if this icon has no image observer
339 * @param g the graphics context
340 * @param x the X coordinate of the icon's top-left corner
341 * @param y the Y coordinate of the icon's top-left corner
342 */
343 public synchronized void paintIcon(Component c, Graphics g, int x,
344 int y) {
345 if (imageObserver == null) {
346 g.drawImage(image, x, y, c);
347 } else {
348 g.drawImage(image, x, y, imageObserver);
349 }
350 }
351
352 /**
353 * Gets the width of the icon.
354 *
355 * @return the width in pixels of this icon
356 */
357 public int getIconWidth() {
358 return width;
359 }
360
361 /**
362 * Gets the height of the icon.
363 *
364 * @return the height in pixels of this icon
365 */
366 public int getIconHeight() {
367 return height;
368 }
369
370 /**
371 * Sets the image observer for the image. Set this
372 * property if the ImageIcon contains an animated GIF, so
373 * the observer is notified to update its display.
374 * For example:
375 * <pre>
376 * icon = new ImageIcon(...)
377 * button.setIcon(icon);
378 * icon.setImageObserver(button);
379 * </pre>
380 *
381 * @param observer the image observer
382 */
383 public void setImageObserver(ImageObserver observer) {
384 imageObserver = observer;
385 }
386
387 /**
388 * Returns the image observer for the image.
389 *
390 * @return the image observer, which may be null
391 */
392 public ImageObserver getImageObserver() {
393 return imageObserver;
394 }
395
396 /**
397 * Returns a string representation of this image.
398 *
399 * @return a string representing this image
400 */
401 public String toString() {
402 if (description != null) {
403 return description;
404 }
405 return super .toString();
406 }
407
408 private void readObject(ObjectInputStream s)
409 throws ClassNotFoundException, IOException {
410 s.defaultReadObject();
411
412 int w = s.readInt();
413 int h = s.readInt();
414 int[] pixels = (int[]) (s.readObject());
415
416 if (pixels != null) {
417 Toolkit tk = Toolkit.getDefaultToolkit();
418 ColorModel cm = ColorModel.getRGBdefault();
419 image = tk.createImage(new MemoryImageSource(w, h, cm,
420 pixels, 0, w));
421 loadImage(image);
422 }
423 }
424
425 private void writeObject(ObjectOutputStream s) throws IOException {
426 s.defaultWriteObject();
427
428 int w = getIconWidth();
429 int h = getIconHeight();
430 int[] pixels = image != null ? new int[w * h] : null;
431
432 if (image != null) {
433 try {
434 PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h,
435 pixels, 0, w);
436 pg.grabPixels();
437 if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
438 throw new IOException(
439 "failed to load image contents");
440 }
441 } catch (InterruptedException e) {
442 throw new IOException("image load interrupted");
443 }
444 }
445
446 s.writeInt(w);
447 s.writeInt(h);
448 s.writeObject(pixels);
449 }
450
451 /**
452 * --- Accessibility Support ---
453 */
454
455 private AccessibleImageIcon accessibleContext = null;
456
457 /**
458 * Gets the AccessibleContext associated with this ImageIcon.
459 * For image icons, the AccessibleContext takes the form of an
460 * AccessibleImageIcon.
461 * A new AccessibleImageIcon instance is created if necessary.
462 *
463 * @return an AccessibleImageIcon that serves as the
464 * AccessibleContext of this ImageIcon
465 * @beaninfo
466 * expert: true
467 * description: The AccessibleContext associated with this ImageIcon.
468 * @since 1.3
469 */
470 public AccessibleContext getAccessibleContext() {
471 if (accessibleContext == null) {
472 accessibleContext = new AccessibleImageIcon();
473 }
474 return accessibleContext;
475 }
476
477 /**
478 * This class implements accessibility support for the
479 * <code>ImageIcon</code> class. It provides an implementation of the
480 * Java Accessibility API appropriate to image icon user-interface
481 * elements.
482 * <p>
483 * <strong>Warning:</strong>
484 * Serialized objects of this class will not be compatible with
485 * future Swing releases. The current serialization support is
486 * appropriate for short term storage or RMI between applications running
487 * the same version of Swing. As of 1.4, support for long term storage
488 * of all JavaBeans<sup><font size="-2">TM</font></sup>
489 * has been added to the <code>java.beans</code> package.
490 * Please see {@link java.beans.XMLEncoder}.
491 * @since 1.3
492 */
493 protected class AccessibleImageIcon extends AccessibleContext
494 implements AccessibleIcon, Serializable {
495
496 /*
497 * AccessibleContest implementation -----------------
498 */
499
500 /**
501 * Gets the role of this object.
502 *
503 * @return an instance of AccessibleRole describing the role of the
504 * object
505 * @see AccessibleRole
506 */
507 public AccessibleRole getAccessibleRole() {
508 return AccessibleRole.ICON;
509 }
510
511 /**
512 * Gets the state of this object.
513 *
514 * @return an instance of AccessibleStateSet containing the current
515 * state set of the object
516 * @see AccessibleState
517 */
518 public AccessibleStateSet getAccessibleStateSet() {
519 return null;
520 }
521
522 /**
523 * Gets the Accessible parent of this object. If the parent of this
524 * object implements Accessible, this method should simply return
525 * getParent().
526 *
527 * @return the Accessible parent of this object -- can be null if this
528 * object does not have an Accessible parent
529 */
530 public Accessible getAccessibleParent() {
531 return null;
532 }
533
534 /**
535 * Gets the index of this object in its accessible parent.
536 *
537 * @return the index of this object in its parent; -1 if this
538 * object does not have an accessible parent.
539 * @see #getAccessibleParent
540 */
541 public int getAccessibleIndexInParent() {
542 return -1;
543 }
544
545 /**
546 * Returns the number of accessible children in the object. If all
547 * of the children of this object implement Accessible, than this
548 * method should return the number of children of this object.
549 *
550 * @return the number of accessible children in the object.
551 */
552 public int getAccessibleChildrenCount() {
553 return 0;
554 }
555
556 /**
557 * Returns the nth Accessible child of the object.
558 *
559 * @param i zero-based index of child
560 * @return the nth Accessible child of the object
561 */
562 public Accessible getAccessibleChild(int i) {
563 return null;
564 }
565
566 /**
567 * Returns the locale of this object.
568 *
569 * @return the locale of this object
570 */
571 public Locale getLocale() throws IllegalComponentStateException {
572 return null;
573 }
574
575 /*
576 * AccessibleIcon implementation -----------------
577 */
578
579 /**
580 * Gets the description of the icon. This is meant to be a brief
581 * textual description of the object. For example, it might be
582 * presented to a blind user to give an indication of the purpose
583 * of the icon.
584 *
585 * @return the description of the icon
586 */
587 public String getAccessibleIconDescription() {
588 return ImageIcon.this .getDescription();
589 }
590
591 /**
592 * Sets the description of the icon. This is meant to be a brief
593 * textual description of the object. For example, it might be
594 * presented to a blind user to give an indication of the purpose
595 * of the icon.
596 *
597 * @param description the description of the icon
598 */
599 public void setAccessibleIconDescription(String description) {
600 ImageIcon.this .setDescription(description);
601 }
602
603 /**
604 * Gets the height of the icon.
605 *
606 * @return the height of the icon
607 */
608 public int getAccessibleIconHeight() {
609 return ImageIcon.this .height;
610 }
611
612 /**
613 * Gets the width of the icon.
614 *
615 * @return the width of the icon
616 */
617 public int getAccessibleIconWidth() {
618 return ImageIcon.this .width;
619 }
620
621 private void readObject(ObjectInputStream s)
622 throws ClassNotFoundException, IOException {
623 s.defaultReadObject();
624 }
625
626 private void writeObject(ObjectOutputStream s)
627 throws IOException {
628 s.defaultWriteObject();
629 }
630 } // AccessibleImageIcon
631 }
|