1. /*
  2. * @(#)ImageIcon.java 1.46 00/04/06
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package javax.swing;
  11. import java.awt.*;
  12. import java.awt.image.*;
  13. import java.net.URL;
  14. import java.io.Serializable;
  15. import java.io.ObjectOutputStream;
  16. import java.io.ObjectInputStream;
  17. import java.io.IOException;
  18. import java.util.Locale;
  19. import javax.accessibility.*;
  20. /**
  21. * An implementation of the Icon interface that paints Icons
  22. * from Images. Images that are created from a URL or filename
  23. * are preloaded using MediaTracker to monitor the loaded state
  24. * of the image.
  25. *
  26. * <p>
  27. * For further information and examples of using image icons, see
  28. * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/icon.html">How to Use Icons</a>
  29. * in <em>The Java Tutorial.</em>
  30. *
  31. * <p>
  32. * <strong>Warning:</strong>
  33. * Serialized objects of this class will not be compatible with
  34. * future Swing releases. The current serialization support is appropriate
  35. * for short term storage or RMI between applications running the same
  36. * version of Swing. A future release of Swing will provide support for
  37. * long term persistence.
  38. *
  39. * @version 1.46 04/06/00
  40. * @author Jeff Dinkins
  41. * @author Lynn Monsanto
  42. */
  43. public class ImageIcon implements Icon, Serializable, Accessible {
  44. /* Keep references to the filename and location so that
  45. * alternate persistence schemes have the option to archive
  46. * images symbolically rather than including the image data
  47. * in the archive.
  48. */
  49. transient private String filename;
  50. transient private URL location;
  51. transient Image image;
  52. transient int loadStatus = 0;
  53. ImageObserver imageObserver;
  54. String description = null;
  55. protected final static Component component = new Component() {};
  56. protected final static MediaTracker tracker = new MediaTracker(component);
  57. int width = -1;
  58. int height = -1;
  59. /**
  60. * Creates an ImageIcon from the specified file. The image will
  61. * be preloaded by using MediaTracker to monitor the loading state
  62. * of the image.
  63. * @param filename the name of the file containing the image
  64. * @param description a brief textual description of the image
  65. * @see #ImageIcon(String)
  66. */
  67. public ImageIcon(String filename, String description) {
  68. image = Toolkit.getDefaultToolkit().getImage(filename);
  69. if (image == null) {
  70. return;
  71. }
  72. this.filename = filename;
  73. this.description = description;
  74. loadImage(image);
  75. }
  76. /**
  77. * Creates an ImageIcon from the specified file. The image will
  78. * be preloaded by using MediaTracker to monitor the loading state
  79. * of the image. The specified String can be a file name or a
  80. * file path. When specifying a path, use the Internet-standard
  81. * forward-slash ("/") as a separator.
  82. * (The string is converted to an URL, so the forward-slash works
  83. * on all systems.)
  84. * For example, specify:
  85. * <pre>
  86. * new ImageIcon("images/myImage.gif") </pre>
  87. * The description is initialized to the <code>filename</code> string.
  88. *
  89. * @param filename a String specifying a filename or path
  90. * @see #getDescription
  91. */
  92. public ImageIcon (String filename) {
  93. this(filename, filename);
  94. }
  95. /**
  96. * Creates an ImageIcon from the specified URL. The image will
  97. * be preloaded by using MediaTracker to monitor the loaded state
  98. * of the image.
  99. * @param location the URL for the image
  100. * @param description a brief textual description of the image
  101. * @see #ImageIcon(String)
  102. */
  103. public ImageIcon(URL location, String description) {
  104. image = Toolkit.getDefaultToolkit().getImage(location);
  105. if (image == null) {
  106. return;
  107. }
  108. this.location = location;
  109. this.description = description;
  110. loadImage(image);
  111. }
  112. /**
  113. * Creates an ImageIcon from the specified URL. The image will
  114. * be preloaded by using MediaTracker to monitor the loaded state
  115. * of the image.
  116. * The icon's description is initialized to be
  117. * a string representation of the URL.
  118. * @param location the URL for the image
  119. * @see #getDescription
  120. */
  121. public ImageIcon (URL location) {
  122. this(location, location.toExternalForm());
  123. }
  124. /**
  125. * Creates an ImageIcon from the image.
  126. * @param image the image
  127. * @param description a brief textual description of the image
  128. */
  129. public ImageIcon(Image image, String description) {
  130. this(image);
  131. this.description = description;
  132. }
  133. /**
  134. * Creates an ImageIcon from an image object.
  135. * If the image has a "comment" property that is a string,
  136. * then the string is used as the description of this icon.
  137. * @param image the image
  138. * @see #getDescription
  139. * @see java.awt.Image#getProperty
  140. */
  141. public ImageIcon (Image image) {
  142. this.image = image;
  143. Object o = image.getProperty("comment", imageObserver);
  144. if (o instanceof String) {
  145. description = (String) o;
  146. }
  147. loadImage(image);
  148. }
  149. /**
  150. * Creates an ImageIcon from an array of bytes which were
  151. * read from an image file containing a supported image format,
  152. * such as GIF or JPEG. Normally this array is created
  153. * by reading an image using Class.getResourceAsStream(), but
  154. * the byte array may also be statically stored in a class.
  155. *
  156. * @param imageData an array of pixels in an image format supported
  157. * by the AWT Toolkit, such as GIF or JPEG.
  158. * @param description a brief textual description of the image
  159. * @see java.awt.Toolkit#createImage
  160. */
  161. public ImageIcon (byte[] imageData, String description) {
  162. this.image = Toolkit.getDefaultToolkit().createImage(imageData);
  163. if (image == null) {
  164. return;
  165. }
  166. this.description = description;
  167. loadImage(image);
  168. }
  169. /**
  170. * Creates an ImageIcon from an array of bytes which were
  171. * read from an image file containing a supported image format,
  172. * such as GIF or JPEG. Normally this array is created
  173. * by reading an image using Class.getResourceAsStream(), but
  174. * the byte array may also be statically stored in a class.
  175. * If the resulting image has a "comment" property that is a string,
  176. * then the string is used as the description of this icon.
  177. *
  178. * @param imageData an array of pixels in an image format supported by
  179. * the AWT Toolkit, such as GIF or JPEG
  180. * @see java.awt.Toolkit#createImage
  181. * @see #getDescription
  182. * @see java.awt.Image#getProperty
  183. */
  184. public ImageIcon (byte[] imageData) {
  185. this.image = Toolkit.getDefaultToolkit().createImage(imageData);
  186. if (image == null) {
  187. return;
  188. }
  189. Object o = image.getProperty("comment", imageObserver);
  190. if (o instanceof String) {
  191. description = (String) o;
  192. }
  193. loadImage(image);
  194. }
  195. /**
  196. * Creates an uninitialized image icon.
  197. */
  198. public ImageIcon() {
  199. }
  200. /**
  201. * Loads the image, returning only when the image is loaded.
  202. * @param image the image
  203. */
  204. protected void loadImage(Image image) {
  205. synchronized(tracker) {
  206. tracker.addImage(image, 0);
  207. try {
  208. tracker.waitForID(0, 0);
  209. } catch (InterruptedException e) {
  210. System.out.println("INTERRUPTED while loading Image");
  211. }
  212. loadStatus = tracker.statusID(0, false);
  213. tracker.removeImage(image, 0);
  214. width = image.getWidth(imageObserver);
  215. height = image.getHeight(imageObserver);
  216. }
  217. }
  218. /**
  219. * Returns the status of the image loading operation.
  220. * @return the loading status as defined by java.awt.MediaTracker
  221. * @see java.awt.MediaTracker#ABORTED
  222. * @see java.awt.MediaTracker#ERRORED
  223. * @see java.awt.MediaTracker#COMPLETE
  224. */
  225. public int getImageLoadStatus() {
  226. return loadStatus;
  227. }
  228. /**
  229. * Returns this icon's <code>Image</code>.
  230. * @return the <code>Image</code> object for this <code>ImageIcon</code>
  231. */
  232. public Image getImage() {
  233. return image;
  234. }
  235. /**
  236. * Sets the image displayed by this icon.
  237. * @param image the image
  238. */
  239. public void setImage(Image image) {
  240. this.image = image;
  241. loadImage(image);
  242. }
  243. /**
  244. * Gets the description of the image. This is meant to be a brief
  245. * textual description of the object. For example, it might be
  246. * presented to a blind user to give an indication of the purpose
  247. * of the image.
  248. * The description may be null.
  249. *
  250. * @return a brief textual description of the image
  251. */
  252. public String getDescription() {
  253. return description;
  254. }
  255. /**
  256. * Sets the description of the image. This is meant to be a brief
  257. * textual description of the object. For example, it might be
  258. * presented to a blind user to give an indication of the purpose
  259. * of the image.
  260. * @param description a brief textual description of the image
  261. */
  262. public void setDescription(String description) {
  263. this.description = description;
  264. }
  265. /**
  266. * Paints the icon.
  267. * The top-left corner of the icon is drawn at
  268. * the point (<code>x</code>, <code>y</code>)
  269. * in the coordinate space of the graphics context <code>g</code>.
  270. * If this icon has no image observer,
  271. * this method uses the <code>c</code> component
  272. * as the observer.
  273. *
  274. * @param c the component to be used as the observer
  275. * if this icon has no image observer
  276. * @param g the graphics context
  277. * @param x the X coordinate of the icon's top-left corner
  278. * @param y the Y coordinate of the icon's top-left corner
  279. */
  280. public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
  281. if(imageObserver == null) {
  282. g.drawImage(image, x, y, c);
  283. } else {
  284. g.drawImage(image, x, y, imageObserver);
  285. }
  286. }
  287. /**
  288. * Gets the width of the icon.
  289. *
  290. * @return the width in pixels of this icon
  291. */
  292. public int getIconWidth() {
  293. return width;
  294. }
  295. /**
  296. * Gets the height of the icon.
  297. *
  298. * @return the height in pixels of this icon
  299. */
  300. public int getIconHeight() {
  301. return height;
  302. }
  303. /**
  304. * Sets the image observer for the image. Set this
  305. * property if the ImageIcon contains an animated GIF, so
  306. * the observer is notified to update its display.
  307. * For example:
  308. * <pre>
  309. * icon = new ImageIcon(...)
  310. * button.setIcon(icon);
  311. * icon.setImageObserver(button);
  312. * </pre>
  313. *
  314. * @param observer the image observer
  315. */
  316. public void setImageObserver(ImageObserver observer) {
  317. imageObserver = observer;
  318. }
  319. /**
  320. * Returns the image observer for the image.
  321. *
  322. * @return the image observer, which may be null
  323. */
  324. public ImageObserver getImageObserver() {
  325. return imageObserver;
  326. }
  327. /**
  328. * Returns a string representation of this image.
  329. *
  330. * @return a string representing this image
  331. */
  332. public String toString() {
  333. return description;
  334. }
  335. private void readObject(ObjectInputStream s)
  336. throws ClassNotFoundException, IOException
  337. {
  338. s.defaultReadObject();
  339. int w = s.readInt();
  340. int h = s.readInt();
  341. int[] pixels = (int[])(s.readObject());
  342. if (pixels != null) {
  343. Toolkit tk = Toolkit.getDefaultToolkit();
  344. ColorModel cm = ColorModel.getRGBdefault();
  345. image = tk.createImage(new MemoryImageSource(w, h, cm, pixels, 0, w));
  346. }
  347. }
  348. private void writeObject(ObjectOutputStream s)
  349. throws IOException
  350. {
  351. s.defaultWriteObject();
  352. int w = getIconWidth();
  353. int h = getIconHeight();
  354. int[] pixels = image != null? new int[w * h] : null;
  355. if (image != null) {
  356. try {
  357. PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
  358. pg.grabPixels();
  359. if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
  360. throw new IOException("failed to load image contents");
  361. }
  362. }
  363. catch (InterruptedException e) {
  364. throw new IOException("image load interrupted");
  365. }
  366. }
  367. s.writeInt(w);
  368. s.writeInt(h);
  369. s.writeObject(pixels);
  370. }
  371. /**
  372. * --- Accessibility Support ---
  373. */
  374. private AccessibleImageIcon accessibleContext = null;
  375. /**
  376. * Gets the AccessibleContext associated with this ImageIcon.
  377. * For image icons, the AccessibleContext takes the form of an
  378. * AccessibleImageIcon.
  379. * A new AccessibleImageIcon instance is created if necessary.
  380. *
  381. * @return an AccessibleImageIcon that serves as the
  382. * AccessibleContext of this ImageIcon
  383. * @beaninfo
  384. * expert: true
  385. * description: The AccessibleContext associated with this ImageIcon.
  386. */
  387. public AccessibleContext getAccessibleContext() {
  388. if (accessibleContext == null) {
  389. accessibleContext = new AccessibleImageIcon();
  390. }
  391. return accessibleContext;
  392. }
  393. /**
  394. * This class implements accessibility support for the
  395. * <code>ImageIcon</code> class. It provides an implementation of the
  396. * Java Accessibility API appropriate to image icon user-interface
  397. * elements.
  398. * <p>
  399. * <strong>Warning:</strong>
  400. * Serialized objects of this class will not be compatible with
  401. * future Swing releases. The current serialization support is appropriate
  402. * for short term storage or RMI between applications running the same
  403. * version of Swing. A future release of Swing will provide support for
  404. * long term persistence.
  405. */
  406. protected class AccessibleImageIcon extends AccessibleContext
  407. implements AccessibleIcon, Serializable {
  408. /*
  409. * AccessibleContest implementation -----------------
  410. */
  411. /**
  412. * Gets the role of this object.
  413. *
  414. * @return an instance of AccessibleRole describing the role of the
  415. * object
  416. * @see AccessibleRole
  417. */
  418. public AccessibleRole getAccessibleRole() {
  419. return AccessibleRole.ICON;
  420. }
  421. /**
  422. * Gets the state of this object.
  423. *
  424. * @return an instance of AccessibleStateSet containing the current
  425. * state set of the object
  426. * @see AccessibleState
  427. */
  428. public AccessibleStateSet getAccessibleStateSet() {
  429. return null;
  430. }
  431. /**
  432. * Gets the Accessible parent of this object. If the parent of this
  433. * object implements Accessible, this method should simply return
  434. * getParent().
  435. *
  436. * @return the Accessible parent of this object -- can be null if this
  437. * object does not have an Accessible parent
  438. */
  439. public Accessible getAccessibleParent() {
  440. return null;
  441. }
  442. /**
  443. * Gets the index of this object in its accessible parent.
  444. *
  445. * @return the index of this object in its parent; -1 if this
  446. * object does not have an accessible parent.
  447. * @see #getAccessibleParent
  448. */
  449. public int getAccessibleIndexInParent() {
  450. return -1;
  451. }
  452. /**
  453. * Returns the number of accessible children in the object. If all
  454. * of the children of this object implement Accessible, than this
  455. * method should return the number of children of this object.
  456. *
  457. * @return the number of accessible children in the object.
  458. */
  459. public int getAccessibleChildrenCount() {
  460. return 0;
  461. }
  462. /**
  463. * Returns the nth Accessible child of the object.
  464. *
  465. * @param i zero-based index of child
  466. * @return the nth Accessible child of the object
  467. */
  468. public Accessible getAccessibleChild(int i) {
  469. return null;
  470. }
  471. /**
  472. * Returns the locale of this object.
  473. *
  474. * @return the locale of this object
  475. */
  476. public Locale getLocale() throws IllegalComponentStateException {
  477. return null;
  478. }
  479. /*
  480. * AccessibleIcon implementation -----------------
  481. */
  482. /**
  483. * Gets the description of the icon. This is meant to be a brief
  484. * textual description of the object. For example, it might be
  485. * presented to a blind user to give an indication of the purpose
  486. * of the icon.
  487. *
  488. * @return the description of the icon
  489. */
  490. public String getAccessibleIconDescription() {
  491. return ImageIcon.this.getDescription();
  492. }
  493. /**
  494. * Sets the description of the icon. This is meant to be a brief
  495. * textual description of the object. For example, it might be
  496. * presented to a blind user to give an indication of the purpose
  497. * of the icon.
  498. *
  499. * @param description the description of the icon
  500. */
  501. public void setAccessibleIconDescription(String description) {
  502. ImageIcon.this.setDescription(description);
  503. }
  504. /**
  505. * Gets the height of the icon.
  506. *
  507. * @return the height of the icon
  508. */
  509. public int getAccessibleIconHeight() {
  510. return ImageIcon.this.height;
  511. }
  512. /**
  513. * Gets the width of the icon.
  514. *
  515. * @return the width of the icon
  516. */
  517. public int getAccessibleIconWidth() {
  518. return ImageIcon.this.width;
  519. }
  520. private void readObject(ObjectInputStream s)
  521. throws ClassNotFoundException, IOException
  522. {
  523. s.defaultReadObject();
  524. }
  525. private void writeObject(ObjectOutputStream s)
  526. throws IOException
  527. {
  528. s.defaultWriteObject();
  529. }
  530. } // AccessibleImageIcon
  531. }