Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]
    1   /*
    2    * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   package javax.swing;
   26   
   27   import java.awt;
   28   import java.awt.image;
   29   import java.beans.ConstructorProperties;
   30   import java.beans.Transient;
   31   import java.net.URL;
   32   
   33   import java.io.Serializable;
   34   import java.io.ObjectOutputStream;
   35   import java.io.ObjectInputStream;
   36   import java.io.IOException;
   37   
   38   import java.util.Locale;
   39   import javax.accessibility;
   40   
   41   import sun.awt.AppContext;
   42   import java.lang.reflect.Field;
   43   import java.security.PrivilegedAction;
   44   import java.security.AccessController;
   45   
   46   /**
   47    * An implementation of the Icon interface that paints Icons
   48    * from Images. Images that are created from a URL, filename or byte array
   49    * are preloaded using MediaTracker to monitor the loaded state
   50    * of the image.
   51    *
   52    * <p>
   53    * For further information and examples of using image icons, see
   54    * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/icon.html">How to Use Icons</a>
   55    * in <em>The Java Tutorial.</em>
   56    *
   57    * <p>
   58    * <strong>Warning:</strong>
   59    * Serialized objects of this class will not be compatible with
   60    * future Swing releases. The current serialization support is
   61    * appropriate for short term storage or RMI between applications running
   62    * the same version of Swing.  As of 1.4, support for long term storage
   63    * of all JavaBeans<sup><font size="-2">TM</font></sup>
   64    * has been added to the <code>java.beans</code> package.
   65    * Please see {@link java.beans.XMLEncoder}.
   66    *
   67    * @author Jeff Dinkins
   68    * @author Lynn Monsanto
   69    */
   70   public class ImageIcon implements Icon, Serializable, Accessible {
   71       /* Keep references to the filename and location so that
   72        * alternate persistence schemes have the option to archive
   73        * images symbolically rather than including the image data
   74        * in the archive.
   75        */
   76       transient private String filename;
   77       transient private URL location;
   78   
   79       transient Image image;
   80       transient int loadStatus = 0;
   81       ImageObserver imageObserver;
   82       String description = null;
   83   
   84       protected final static Component component;
   85       protected final static MediaTracker tracker;
   86   
   87       static {
   88           component = new Component() {};
   89           AccessController.doPrivileged(new PrivilegedAction() {
   90               public Object run() {
   91                   try {
   92                       // 6482575 - clear the appContext field so as not to leak it
   93                       Field appContextField =
   94                                    Component.class.getDeclaredField("appContext");
   95                       appContextField.setAccessible(true);
   96                       appContextField.set(component, null);
   97                   }
   98                   catch (NoSuchFieldException e) {
   99                       e.printStackTrace();
  100                   }
  101                   catch (IllegalAccessException e) {
  102                       e.printStackTrace();
  103                   }
  104                   return null;
  105               }
  106           });
  107           tracker = new MediaTracker(component);
  108       }
  109   
  110       /**
  111        * Id used in loading images from MediaTracker.
  112        */
  113       private static int mediaTrackerID;
  114   
  115       private final static Object TRACKER_KEY = new StringBuilder("TRACKER_KEY");
  116   
  117       int width = -1;
  118       int height = -1;
  119   
  120       /**
  121        * Creates an ImageIcon from the specified file. The image will
  122        * be preloaded by using MediaTracker to monitor the loading state
  123        * of the image.
  124        * @param filename the name of the file containing the image
  125        * @param description a brief textual description of the image
  126        * @see #ImageIcon(String)
  127        */
  128       public ImageIcon(String filename, String description) {
  129           image = Toolkit.getDefaultToolkit().getImage(filename);
  130           if (image == null) {
  131               return;
  132           }
  133           this.filename = filename;
  134           this.description = description;
  135           loadImage(image);
  136       }
  137   
  138       /**
  139        * Creates an ImageIcon from the specified file. The image will
  140        * be preloaded by using MediaTracker to monitor the loading state
  141        * of the image. The specified String can be a file name or a
  142        * file path. When specifying a path, use the Internet-standard
  143        * forward-slash ("/") as a separator.
  144        * (The string is converted to an URL, so the forward-slash works
  145        * on all systems.)
  146        * For example, specify:
  147        * <pre>
  148        *    new ImageIcon("images/myImage.gif") </pre>
  149        * The description is initialized to the <code>filename</code> string.
  150        *
  151        * @param filename a String specifying a filename or path
  152        * @see #getDescription
  153        */
  154       @ConstructorProperties({"description"})
  155       public ImageIcon (String filename) {
  156           this(filename, filename);
  157       }
  158   
  159       /**
  160        * Creates an ImageIcon from the specified URL. The image will
  161        * be preloaded by using MediaTracker to monitor the loaded state
  162        * of the image.
  163        * @param location the URL for the image
  164        * @param description a brief textual description of the image
  165        * @see #ImageIcon(String)
  166        */
  167       public ImageIcon(URL location, String description) {
  168           image = Toolkit.getDefaultToolkit().getImage(location);
  169           if (image == null) {
  170               return;
  171           }
  172           this.location = location;
  173           this.description = description;
  174           loadImage(image);
  175       }
  176   
  177       /**
  178        * Creates an ImageIcon from the specified URL. The image will
  179        * be preloaded by using MediaTracker to monitor the loaded state
  180        * of the image.
  181        * The icon's description is initialized to be
  182        * a string representation of the URL.
  183        * @param location the URL for the image
  184        * @see #getDescription
  185        */
  186       public ImageIcon (URL location) {
  187           this(location, location.toExternalForm());
  188       }
  189   
  190       /**
  191        * Creates an ImageIcon from the image.
  192        * @param image the image
  193        * @param description a brief textual description of the image
  194        */
  195       public ImageIcon(Image image, String description) {
  196           this(image);
  197           this.description = description;
  198       }
  199   
  200       /**
  201        * Creates an ImageIcon from an image object.
  202        * If the image has a "comment" property that is a string,
  203        * then the string is used as the description of this icon.
  204        * @param image the image
  205        * @see #getDescription
  206        * @see java.awt.Image#getProperty
  207        */
  208       public ImageIcon (Image image) {
  209           this.image = image;
  210           Object o = image.getProperty("comment", imageObserver);
  211           if (o instanceof String) {
  212               description = (String) o;
  213           }
  214           loadImage(image);
  215       }
  216   
  217       /**
  218        * Creates an ImageIcon from an array of bytes which were
  219        * read from an image file containing a supported image format,
  220        * such as GIF, JPEG, or (as of 1.3) PNG.
  221        * Normally this array is created
  222        * by reading an image using Class.getResourceAsStream(), but
  223        * the byte array may also be statically stored in a class.
  224        *
  225        * @param  imageData an array of pixels in an image format supported
  226        *         by the AWT Toolkit, such as GIF, JPEG, or (as of 1.3) PNG
  227        * @param  description a brief textual description of the image
  228        * @see    java.awt.Toolkit#createImage
  229        */
  230       public ImageIcon (byte[] imageData, String description) {
  231           this.image = Toolkit.getDefaultToolkit().createImage(imageData);
  232           if (image == null) {
  233               return;
  234           }
  235           this.description = description;
  236           loadImage(image);
  237       }
  238   
  239       /**
  240        * Creates an ImageIcon from an array of bytes which were
  241        * read from an image file containing a supported image format,
  242        * such as GIF, JPEG, or (as of 1.3) PNG.
  243        * Normally this array is created
  244        * by reading an image using Class.getResourceAsStream(), but
  245        * the byte array may also be statically stored in a class.
  246        * If the resulting image has a "comment" property that is a string,
  247        * then the string is used as the description of this icon.
  248        *
  249        * @param  imageData an array of pixels in an image format supported by
  250        *             the AWT Toolkit, such as GIF, JPEG, or (as of 1.3) PNG
  251        * @see    java.awt.Toolkit#createImage
  252        * @see #getDescription
  253        * @see java.awt.Image#getProperty
  254        */
  255       public ImageIcon (byte[] imageData) {
  256           this.image = Toolkit.getDefaultToolkit().createImage(imageData);
  257           if (image == null) {
  258               return;
  259           }
  260           Object o = image.getProperty("comment", imageObserver);
  261           if (o instanceof String) {
  262               description = (String) o;
  263           }
  264           loadImage(image);
  265       }
  266   
  267       /**
  268        * Creates an uninitialized image icon.
  269        */
  270       public ImageIcon() {
  271       }
  272   
  273       /**
  274        * Loads the image, returning only when the image is loaded.
  275        * @param image the image
  276        */
  277       protected void loadImage(Image image) {
  278           MediaTracker mTracker = getTracker();
  279           synchronized(mTracker) {
  280               int id = getNextID();
  281   
  282               mTracker.addImage(image, id);
  283               try {
  284                   mTracker.waitForID(id, 0);
  285               } catch (InterruptedException e) {
  286                   System.out.println("INTERRUPTED while loading Image");
  287               }
  288               loadStatus = mTracker.statusID(id, false);
  289               mTracker.removeImage(image, id);
  290   
  291               width = image.getWidth(imageObserver);
  292               height = image.getHeight(imageObserver);
  293           }
  294       }
  295   
  296       /**
  297        * Returns an ID to use with the MediaTracker in loading an image.
  298        */
  299       private int getNextID() {
  300           synchronized(getTracker()) {
  301               return ++mediaTrackerID;
  302           }
  303       }
  304   
  305       /**
  306        * Returns the MediaTracker for the current AppContext, creating a new
  307        * MediaTracker if necessary.
  308        */
  309       private MediaTracker getTracker() {
  310           Object trackerObj;
  311           AppContext ac = AppContext.getAppContext();
  312           // Opt: Only synchronize if trackerObj comes back null?
  313           // If null, synchronize, re-check for null, and put new tracker
  314           synchronized(ac) {
  315               trackerObj = ac.get(TRACKER_KEY);
  316               if (trackerObj == null) {
  317                   Component comp = new Component() {};
  318                   trackerObj = new MediaTracker(comp);
  319                   ac.put(TRACKER_KEY, trackerObj);
  320               }
  321           }
  322           return (MediaTracker) trackerObj;
  323       }
  324   
  325       /**
  326        * Returns the status of the image loading operation.
  327        * @return the loading status as defined by java.awt.MediaTracker
  328        * @see java.awt.MediaTracker#ABORTED
  329        * @see java.awt.MediaTracker#ERRORED
  330        * @see java.awt.MediaTracker#COMPLETE
  331        */
  332       public int getImageLoadStatus() {
  333           return loadStatus;
  334       }
  335   
  336       /**
  337        * Returns this icon's <code>Image</code>.
  338        * @return the <code>Image</code> object for this <code>ImageIcon</code>
  339        */
  340       @Transient
  341       public Image getImage() {
  342           return image;
  343       }
  344   
  345       /**
  346        * Sets the image displayed by this icon.
  347        * @param image the image
  348        */
  349       public void setImage(Image image) {
  350           this.image = image;
  351           loadImage(image);
  352       }
  353   
  354       /**
  355        * Gets the description of the image.  This is meant to be a brief
  356        * textual description of the object.  For example, it might be
  357        * presented to a blind user to give an indication of the purpose
  358        * of the image.
  359        * The description may be null.
  360        *
  361        * @return a brief textual description of the image
  362        */
  363       public String getDescription() {
  364           return description;
  365       }
  366   
  367       /**
  368        * Sets the description of the image.  This is meant to be a brief
  369        * textual description of the object.  For example, it might be
  370        * presented to a blind user to give an indication of the purpose
  371        * of the image.
  372        * @param description a brief textual description of the image
  373        */
  374       public void setDescription(String description) {
  375           this.description = description;
  376       }
  377   
  378       /**
  379        * Paints the icon.
  380        * The top-left corner of the icon is drawn at
  381        * the point (<code>x</code>, <code>y</code>)
  382        * in the coordinate space of the graphics context <code>g</code>.
  383        * If this icon has no image observer,
  384        * this method uses the <code>c</code> component
  385        * as the observer.
  386        *
  387        * @param c the component to be used as the observer
  388        *          if this icon has no image observer
  389        * @param g the graphics context
  390        * @param x the X coordinate of the icon's top-left corner
  391        * @param y the Y coordinate of the icon's top-left corner
  392        */
  393       public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
  394           if(imageObserver == null) {
  395              g.drawImage(image, x, y, c);
  396           } else {
  397              g.drawImage(image, x, y, imageObserver);
  398           }
  399       }
  400   
  401       /**
  402        * Gets the width of the icon.
  403        *
  404        * @return the width in pixels of this icon
  405        */
  406       public int getIconWidth() {
  407           return width;
  408       }
  409   
  410       /**
  411        * Gets the height of the icon.
  412        *
  413        * @return the height in pixels of this icon
  414        */
  415       public int getIconHeight() {
  416           return height;
  417       }
  418   
  419       /**
  420        * Sets the image observer for the image.  Set this
  421        * property if the ImageIcon contains an animated GIF, so
  422        * the observer is notified to update its display.
  423        * For example:
  424        * <pre>
  425        *     icon = new ImageIcon(...)
  426        *     button.setIcon(icon);
  427        *     icon.setImageObserver(button);
  428        * </pre>
  429        *
  430        * @param observer the image observer
  431        */
  432       public void setImageObserver(ImageObserver observer) {
  433           imageObserver = observer;
  434       }
  435   
  436       /**
  437        * Returns the image observer for the image.
  438        *
  439        * @return the image observer, which may be null
  440        */
  441       @Transient
  442       public ImageObserver getImageObserver() {
  443           return imageObserver;
  444       }
  445   
  446       /**
  447        * Returns a string representation of this image.
  448        *
  449        * @return a string representing this image
  450        */
  451       public String toString() {
  452           if (description != null) {
  453               return description;
  454           }
  455           return super.toString();
  456       }
  457   
  458       private void readObject(ObjectInputStream s)
  459           throws ClassNotFoundException, IOException
  460       {
  461           s.defaultReadObject();
  462   
  463           int w = s.readInt();
  464           int h = s.readInt();
  465           int[] pixels = (int[])(s.readObject());
  466   
  467           if (pixels != null) {
  468               Toolkit tk = Toolkit.getDefaultToolkit();
  469               ColorModel cm = ColorModel.getRGBdefault();
  470               image = tk.createImage(new MemoryImageSource(w, h, cm, pixels, 0, w));
  471               loadImage(image);
  472           }
  473       }
  474   
  475   
  476       private void writeObject(ObjectOutputStream s)
  477           throws IOException
  478       {
  479           s.defaultWriteObject();
  480   
  481           int w = getIconWidth();
  482           int h = getIconHeight();
  483           int[] pixels = image != null? new int[w * h] : null;
  484   
  485           if (image != null) {
  486               try {
  487                   PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
  488                   pg.grabPixels();
  489                   if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
  490                       throw new IOException("failed to load image contents");
  491                   }
  492               }
  493               catch (InterruptedException e) {
  494                   throw new IOException("image load interrupted");
  495               }
  496           }
  497   
  498           s.writeInt(w);
  499           s.writeInt(h);
  500           s.writeObject(pixels);
  501       }
  502   
  503       /**
  504        * --- Accessibility Support ---
  505        */
  506   
  507       private AccessibleImageIcon accessibleContext = null;
  508   
  509       /**
  510        * Gets the AccessibleContext associated with this ImageIcon.
  511        * For image icons, the AccessibleContext takes the form of an
  512        * AccessibleImageIcon.
  513        * A new AccessibleImageIcon instance is created if necessary.
  514        *
  515        * @return an AccessibleImageIcon that serves as the
  516        *         AccessibleContext of this ImageIcon
  517        * @beaninfo
  518        *       expert: true
  519        *  description: The AccessibleContext associated with this ImageIcon.
  520        * @since 1.3
  521        */
  522       public AccessibleContext getAccessibleContext() {
  523           if (accessibleContext == null) {
  524               accessibleContext = new AccessibleImageIcon();
  525           }
  526           return accessibleContext;
  527       }
  528   
  529       /**
  530        * This class implements accessibility support for the
  531        * <code>ImageIcon</code> class.  It provides an implementation of the
  532        * Java Accessibility API appropriate to image icon user-interface
  533        * elements.
  534        * <p>
  535        * <strong>Warning:</strong>
  536        * Serialized objects of this class will not be compatible with
  537        * future Swing releases. The current serialization support is
  538        * appropriate for short term storage or RMI between applications running
  539        * the same version of Swing.  As of 1.4, support for long term storage
  540        * of all JavaBeans<sup><font size="-2">TM</font></sup>
  541        * has been added to the <code>java.beans</code> package.
  542        * Please see {@link java.beans.XMLEncoder}.
  543        * @since 1.3
  544        */
  545       protected class AccessibleImageIcon extends AccessibleContext
  546           implements AccessibleIcon, Serializable {
  547   
  548           /*
  549            * AccessibleContest implementation -----------------
  550            */
  551   
  552           /**
  553            * Gets the role of this object.
  554            *
  555            * @return an instance of AccessibleRole describing the role of the
  556            * object
  557            * @see AccessibleRole
  558            */
  559           public AccessibleRole getAccessibleRole() {
  560               return AccessibleRole.ICON;
  561           }
  562   
  563           /**
  564            * Gets the state of this object.
  565            *
  566            * @return an instance of AccessibleStateSet containing the current
  567            * state set of the object
  568            * @see AccessibleState
  569            */
  570           public AccessibleStateSet getAccessibleStateSet() {
  571               return null;
  572           }
  573   
  574           /**
  575            * Gets the Accessible parent of this object.  If the parent of this
  576            * object implements Accessible, this method should simply return
  577            * getParent().
  578            *
  579            * @return the Accessible parent of this object -- can be null if this
  580            * object does not have an Accessible parent
  581            */
  582           public Accessible getAccessibleParent() {
  583               return null;
  584           }
  585   
  586           /**
  587            * Gets the index of this object in its accessible parent.
  588            *
  589            * @return the index of this object in its parent; -1 if this
  590            * object does not have an accessible parent.
  591            * @see #getAccessibleParent
  592            */
  593           public int getAccessibleIndexInParent() {
  594               return -1;
  595           }
  596   
  597           /**
  598            * Returns the number of accessible children in the object.  If all
  599            * of the children of this object implement Accessible, than this
  600            * method should return the number of children of this object.
  601            *
  602            * @return the number of accessible children in the object.
  603            */
  604           public int getAccessibleChildrenCount() {
  605               return 0;
  606           }
  607   
  608           /**
  609            * Returns the nth Accessible child of the object.
  610            *
  611            * @param i zero-based index of child
  612            * @return the nth Accessible child of the object
  613            */
  614           public Accessible getAccessibleChild(int i) {
  615               return null;
  616           }
  617   
  618           /**
  619            * Returns the locale of this object.
  620            *
  621            * @return the locale of this object
  622            */
  623           public Locale getLocale() throws IllegalComponentStateException {
  624               return null;
  625           }
  626   
  627           /*
  628            * AccessibleIcon implementation -----------------
  629            */
  630   
  631           /**
  632            * Gets the description of the icon.  This is meant to be a brief
  633            * textual description of the object.  For example, it might be
  634            * presented to a blind user to give an indication of the purpose
  635            * of the icon.
  636            *
  637            * @return the description of the icon
  638            */
  639           public String getAccessibleIconDescription() {
  640               return ImageIcon.this.getDescription();
  641           }
  642   
  643           /**
  644            * Sets the description of the icon.  This is meant to be a brief
  645            * textual description of the object.  For example, it might be
  646            * presented to a blind user to give an indication of the purpose
  647            * of the icon.
  648            *
  649            * @param description the description of the icon
  650            */
  651           public void setAccessibleIconDescription(String description) {
  652               ImageIcon.this.setDescription(description);
  653           }
  654   
  655           /**
  656            * Gets the height of the icon.
  657            *
  658            * @return the height of the icon
  659            */
  660           public int getAccessibleIconHeight() {
  661               return ImageIcon.this.height;
  662           }
  663   
  664           /**
  665            * Gets the width of the icon.
  666            *
  667            * @return the width of the icon
  668            */
  669           public int getAccessibleIconWidth() {
  670               return ImageIcon.this.width;
  671           }
  672   
  673           private void readObject(ObjectInputStream s)
  674               throws ClassNotFoundException, IOException
  675           {
  676               s.defaultReadObject();
  677           }
  678   
  679           private void writeObject(ObjectOutputStream s)
  680               throws IOException
  681           {
  682               s.defaultWriteObject();
  683           }
  684       }  // AccessibleImageIcon
  685   }

Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]