Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    * Copyright (c) 1995, 2007, Oracle and/or its affiliates. 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.awt;
   27   
   28   import java.awt.Component;
   29   import java.awt.Image;
   30   import java.awt.image.ImageObserver;
   31   
   32   /**
   33    * The <code>MediaTracker</code> class is a utility class to track
   34    * the status of a number of media objects. Media objects could
   35    * include audio clips as well as images, though currently only
   36    * images are supported.
   37    * <p>
   38    * To use a media tracker, create an instance of
   39    * <code>MediaTracker</code> and call its <code>addImage</code>
   40    * method for each image to be tracked. In addition, each image can
   41    * be assigned a unique identifier. This identifier controls the
   42    * priority order in which the images are fetched. It can also be used
   43    * to identify unique subsets of the images that can be waited on
   44    * independently. Images with a lower ID are loaded in preference to
   45    * those with a higher ID number.
   46    *
   47    * <p>
   48    *
   49    * Tracking an animated image
   50    * might not always be useful
   51    * due to the multi-part nature of animated image
   52    * loading and painting,
   53    * but it is supported.
   54    * <code>MediaTracker</code> treats an animated image
   55    * as completely loaded
   56    * when the first frame is completely loaded.
   57    * At that point, the <code>MediaTracker</code>
   58    * signals any waiters
   59    * that the image is completely loaded.
   60    * If no <code>ImageObserver</code>s are observing the image
   61    * when the first frame has finished loading,
   62    * the image might flush itself
   63    * to conserve resources
   64    * (see {@link Image#flush()}).
   65    *
   66    * <p>
   67    * Here is an example of using <code>MediaTracker</code>:
   68    * <p>
   69    * <hr><blockquote><pre>
   70    * import java.applet.Applet;
   71    * import java.awt.Color;
   72    * import java.awt.Image;
   73    * import java.awt.Graphics;
   74    * import java.awt.MediaTracker;
   75    *
   76    * public class ImageBlaster extends Applet implements Runnable {
   77    *      MediaTracker tracker;
   78    *      Image bg;
   79    *      Image anim[] = new Image[5];
   80    *      int index;
   81    *      Thread animator;
   82    *
   83    *      // Get the images for the background (id == 0)
   84    *      // and the animation frames (id == 1)
   85    *      // and add them to the MediaTracker
   86    *      public void init() {
   87    *          tracker = new MediaTracker(this);
   88    *          bg = getImage(getDocumentBase(),
   89    *                  "images/background.gif");
   90    *          tracker.addImage(bg, 0);
   91    *          for (int i = 0; i < 5; i++) {
   92    *              anim[i] = getImage(getDocumentBase(),
   93    *                      "images/anim"+i+".gif");
   94    *              tracker.addImage(anim[i], 1);
   95    *          }
   96    *      }
   97    *
   98    *      // Start the animation thread.
   99    *      public void start() {
  100    *          animator = new Thread(this);
  101    *          animator.start();
  102    *      }
  103    *
  104    *      // Stop the animation thread.
  105    *      public void stop() {
  106    *          animator = null;
  107    *      }
  108    *
  109    *      // Run the animation thread.
  110    *      // First wait for the background image to fully load
  111    *      // and paint.  Then wait for all of the animation
  112    *      // frames to finish loading. Finally, loop and
  113    *      // increment the animation frame index.
  114    *      public void run() {
  115    *          try {
  116    *              tracker.waitForID(0);
  117    *              tracker.waitForID(1);
  118    *          } catch (InterruptedException e) {
  119    *              return;
  120    *          }
  121    *          Thread me = Thread.currentThread();
  122    *          while (animator == me) {
  123    *              try {
  124    *                  Thread.sleep(100);
  125    *              } catch (InterruptedException e) {
  126    *                  break;
  127    *              }
  128    *              synchronized (this) {
  129    *                  index++;
  130    *                  if (index >= anim.length) {
  131    *                      index = 0;
  132    *                  }
  133    *              }
  134    *              repaint();
  135    *          }
  136    *      }
  137    *
  138    *      // The background image fills the frame so we
  139    *      // don't need to clear the applet on repaints.
  140    *      // Just call the paint method.
  141    *      public void update(Graphics g) {
  142    *          paint(g);
  143    *      }
  144    *
  145    *      // Paint a large red rectangle if there are any errors
  146    *      // loading the images.  Otherwise always paint the
  147    *      // background so that it appears incrementally as it
  148    *      // is loading.  Finally, only paint the current animation
  149    *      // frame if all of the frames (id == 1) are done loading,
  150    *      // so that we don't get partial animations.
  151    *      public void paint(Graphics g) {
  152    *          if ((tracker.statusAll(false) & MediaTracker.ERRORED) != 0) {
  153    *              g.setColor(Color.red);
  154    *              g.fillRect(0, 0, size().width, size().height);
  155    *              return;
  156    *          }
  157    *          g.drawImage(bg, 0, 0, this);
  158    *          if (tracker.statusID(1, false) == MediaTracker.COMPLETE) {
  159    *              g.drawImage(anim[index], 10, 10, this);
  160    *          }
  161    *      }
  162    * }
  163    * </pre></blockquote><hr>
  164    *
  165    * @author      Jim Graham
  166    * @since       JDK1.0
  167    */
  168   public class MediaTracker implements java.io.Serializable {
  169   
  170       /**
  171        * A given <code>Component</code> that will be
  172        * tracked by a media tracker where the image will
  173        * eventually be drawn.
  174        *
  175        * @serial
  176        * @see #MediaTracker(Component)
  177        */
  178       Component target;
  179       /**
  180        * The head of the list of <code>Images</code> that is being
  181        * tracked by the <code>MediaTracker</code>.
  182        *
  183        * @serial
  184        * @see #addImage(Image, int)
  185        * @see #removeImage(Image)
  186        */
  187       MediaEntry head;
  188   
  189       /*
  190        * JDK 1.1 serialVersionUID
  191        */
  192       private static final long serialVersionUID = -483174189758638095L;
  193   
  194       /**
  195        * Creates a media tracker to track images for a given component.
  196        * @param     comp the component on which the images
  197        *                     will eventually be drawn
  198        */
  199       public MediaTracker(Component comp) {
  200           target = comp;
  201       }
  202   
  203       /**
  204        * Adds an image to the list of images being tracked by this media
  205        * tracker. The image will eventually be rendered at its default
  206        * (unscaled) size.
  207        * @param     image   the image to be tracked
  208        * @param     id      an identifier used to track this image
  209        */
  210       public void addImage(Image image, int id) {
  211           addImage(image, id, -1, -1);
  212       }
  213   
  214       /**
  215        * Adds a scaled image to the list of images being tracked
  216        * by this media tracker. The image will eventually be
  217        * rendered at the indicated width and height.
  218        *
  219        * @param     image   the image to be tracked
  220        * @param     id   an identifier that can be used to track this image
  221        * @param     w    the width at which the image is rendered
  222        * @param     h    the height at which the image is rendered
  223        */
  224       public synchronized void addImage(Image image, int id, int w, int h) {
  225           head = MediaEntry.insert(head,
  226                                    new ImageMediaEntry(this, image, id, w, h));
  227       }
  228   
  229       /**
  230        * Flag indicating that media is currently being loaded.
  231        * @see         java.awt.MediaTracker#statusAll
  232        * @see         java.awt.MediaTracker#statusID
  233        */
  234       public static final int LOADING = 1;
  235   
  236       /**
  237        * Flag indicating that the downloading of media was aborted.
  238        * @see         java.awt.MediaTracker#statusAll
  239        * @see         java.awt.MediaTracker#statusID
  240        */
  241       public static final int ABORTED = 2;
  242   
  243       /**
  244        * Flag indicating that the downloading of media encountered
  245        * an error.
  246        * @see         java.awt.MediaTracker#statusAll
  247        * @see         java.awt.MediaTracker#statusID
  248        */
  249       public static final int ERRORED = 4;
  250   
  251       /**
  252        * Flag indicating that the downloading of media was completed
  253        * successfully.
  254        * @see         java.awt.MediaTracker#statusAll
  255        * @see         java.awt.MediaTracker#statusID
  256        */
  257       public static final int COMPLETE = 8;
  258   
  259       static final int DONE = (ABORTED | ERRORED | COMPLETE);
  260   
  261       /**
  262        * Checks to see if all images being tracked by this media tracker
  263        * have finished loading.
  264        * <p>
  265        * This method does not start loading the images if they are not
  266        * already loading.
  267        * <p>
  268        * If there is an error while loading or scaling an image, then that
  269        * image is considered to have finished loading. Use the
  270        * <code>isErrorAny</code> or <code>isErrorID</code> methods to
  271        * check for errors.
  272        * @return      <code>true</code> if all images have finished loading,
  273        *                       have been aborted, or have encountered
  274        *                       an error; <code>false</code> otherwise
  275        * @see         java.awt.MediaTracker#checkAll(boolean)
  276        * @see         java.awt.MediaTracker#checkID
  277        * @see         java.awt.MediaTracker#isErrorAny
  278        * @see         java.awt.MediaTracker#isErrorID
  279        */
  280       public boolean checkAll() {
  281           return checkAll(false, true);
  282       }
  283   
  284       /**
  285        * Checks to see if all images being tracked by this media tracker
  286        * have finished loading.
  287        * <p>
  288        * If the value of the <code>load</code> flag is <code>true</code>,
  289        * then this method starts loading any images that are not yet
  290        * being loaded.
  291        * <p>
  292        * If there is an error while loading or scaling an image, that
  293        * image is considered to have finished loading. Use the
  294        * <code>isErrorAny</code> and <code>isErrorID</code> methods to
  295        * check for errors.
  296        * @param       load   if <code>true</code>, start loading any
  297        *                       images that are not yet being loaded
  298        * @return      <code>true</code> if all images have finished loading,
  299        *                       have been aborted, or have encountered
  300        *                       an error; <code>false</code> otherwise
  301        * @see         java.awt.MediaTracker#checkID
  302        * @see         java.awt.MediaTracker#checkAll()
  303        * @see         java.awt.MediaTracker#isErrorAny()
  304        * @see         java.awt.MediaTracker#isErrorID(int)
  305        */
  306       public boolean checkAll(boolean load) {
  307           return checkAll(load, true);
  308       }
  309   
  310       private synchronized boolean checkAll(boolean load, boolean verify) {
  311           MediaEntry cur = head;
  312           boolean done = true;
  313           while (cur != null) {
  314               if ((cur.getStatus(load, verify) & DONE) == 0) {
  315                   done = false;
  316               }
  317               cur = cur.next;
  318           }
  319           return done;
  320       }
  321   
  322       /**
  323        * Checks the error status of all of the images.
  324        * @return   <code>true</code> if any of the images tracked
  325        *                  by this media tracker had an error during
  326        *                  loading; <code>false</code> otherwise
  327        * @see      java.awt.MediaTracker#isErrorID
  328        * @see      java.awt.MediaTracker#getErrorsAny
  329        */
  330       public synchronized boolean isErrorAny() {
  331           MediaEntry cur = head;
  332           while (cur != null) {
  333               if ((cur.getStatus(false, true) & ERRORED) != 0) {
  334                   return true;
  335               }
  336               cur = cur.next;
  337           }
  338           return false;
  339       }
  340   
  341       /**
  342        * Returns a list of all media that have encountered an error.
  343        * @return       an array of media objects tracked by this
  344        *                        media tracker that have encountered
  345        *                        an error, or <code>null</code> if
  346        *                        there are none with errors
  347        * @see          java.awt.MediaTracker#isErrorAny
  348        * @see          java.awt.MediaTracker#getErrorsID
  349        */
  350       public synchronized Object[] getErrorsAny() {
  351           MediaEntry cur = head;
  352           int numerrors = 0;
  353           while (cur != null) {
  354               if ((cur.getStatus(false, true) & ERRORED) != 0) {
  355                   numerrors++;
  356               }
  357               cur = cur.next;
  358           }
  359           if (numerrors == 0) {
  360               return null;
  361           }
  362           Object errors[] = new Object[numerrors];
  363           cur = head;
  364           numerrors = 0;
  365           while (cur != null) {
  366               if ((cur.getStatus(false, false) & ERRORED) != 0) {
  367                   errors[numerrors++] = cur.getMedia();
  368               }
  369               cur = cur.next;
  370           }
  371           return errors;
  372       }
  373   
  374       /**
  375        * Starts loading all images tracked by this media tracker. This
  376        * method waits until all the images being tracked have finished
  377        * loading.
  378        * <p>
  379        * If there is an error while loading or scaling an image, then that
  380        * image is considered to have finished loading. Use the
  381        * <code>isErrorAny</code> or <code>isErrorID</code> methods to
  382        * check for errors.
  383        * @see         java.awt.MediaTracker#waitForID(int)
  384        * @see         java.awt.MediaTracker#waitForAll(long)
  385        * @see         java.awt.MediaTracker#isErrorAny
  386        * @see         java.awt.MediaTracker#isErrorID
  387        * @exception   InterruptedException  if any thread has
  388        *                                     interrupted this thread
  389        */
  390       public void waitForAll() throws InterruptedException {
  391           waitForAll(0);
  392       }
  393   
  394       /**
  395        * Starts loading all images tracked by this media tracker. This
  396        * method waits until all the images being tracked have finished
  397        * loading, or until the length of time specified in milliseconds
  398        * by the <code>ms</code> argument has passed.
  399        * <p>
  400        * If there is an error while loading or scaling an image, then
  401        * that image is considered to have finished loading. Use the
  402        * <code>isErrorAny</code> or <code>isErrorID</code> methods to
  403        * check for errors.
  404        * @param       ms       the number of milliseconds to wait
  405        *                       for the loading to complete
  406        * @return      <code>true</code> if all images were successfully
  407        *                       loaded; <code>false</code> otherwise
  408        * @see         java.awt.MediaTracker#waitForID(int)
  409        * @see         java.awt.MediaTracker#waitForAll(long)
  410        * @see         java.awt.MediaTracker#isErrorAny
  411        * @see         java.awt.MediaTracker#isErrorID
  412        * @exception   InterruptedException  if any thread has
  413        *                                     interrupted this thread.
  414        */
  415       public synchronized boolean waitForAll(long ms)
  416           throws InterruptedException
  417       {
  418           long end = System.currentTimeMillis() + ms;
  419           boolean first = true;
  420           while (true) {
  421               int status = statusAll(first, first);
  422               if ((status & LOADING) == 0) {
  423                   return (status == COMPLETE);
  424               }
  425               first = false;
  426               long timeout;
  427               if (ms == 0) {
  428                   timeout = 0;
  429               } else {
  430                   timeout = end - System.currentTimeMillis();
  431                   if (timeout <= 0) {
  432                       return false;
  433                   }
  434               }
  435               wait(timeout);
  436           }
  437       }
  438   
  439       /**
  440        * Calculates and returns the bitwise inclusive <b>OR</b> of the
  441        * status of all media that are tracked by this media tracker.
  442        * <p>
  443        * Possible flags defined by the
  444        * <code>MediaTracker</code> class are <code>LOADING</code>,
  445        * <code>ABORTED</code>, <code>ERRORED</code>, and
  446        * <code>COMPLETE</code>. An image that hasn't started
  447        * loading has zero as its status.
  448        * <p>
  449        * If the value of <code>load</code> is <code>true</code>, then
  450        * this method starts loading any images that are not yet being loaded.
  451        *
  452        * @param        load   if <code>true</code>, start loading
  453        *                            any images that are not yet being loaded
  454        * @return       the bitwise inclusive <b>OR</b> of the status of
  455        *                            all of the media being tracked
  456        * @see          java.awt.MediaTracker#statusID(int, boolean)
  457        * @see          java.awt.MediaTracker#LOADING
  458        * @see          java.awt.MediaTracker#ABORTED
  459        * @see          java.awt.MediaTracker#ERRORED
  460        * @see          java.awt.MediaTracker#COMPLETE
  461        */
  462       public int statusAll(boolean load) {
  463           return statusAll(load, true);
  464       }
  465   
  466       private synchronized int statusAll(boolean load, boolean verify) {
  467           MediaEntry cur = head;
  468           int status = 0;
  469           while (cur != null) {
  470               status = status | cur.getStatus(load, verify);
  471               cur = cur.next;
  472           }
  473           return status;
  474       }
  475   
  476       /**
  477        * Checks to see if all images tracked by this media tracker that
  478        * are tagged with the specified identifier have finished loading.
  479        * <p>
  480        * This method does not start loading the images if they are not
  481        * already loading.
  482        * <p>
  483        * If there is an error while loading or scaling an image, then that
  484        * image is considered to have finished loading. Use the
  485        * <code>isErrorAny</code> or <code>isErrorID</code> methods to
  486        * check for errors.
  487        * @param       id   the identifier of the images to check
  488        * @return      <code>true</code> if all images have finished loading,
  489        *                       have been aborted, or have encountered
  490        *                       an error; <code>false</code> otherwise
  491        * @see         java.awt.MediaTracker#checkID(int, boolean)
  492        * @see         java.awt.MediaTracker#checkAll()
  493        * @see         java.awt.MediaTracker#isErrorAny()
  494        * @see         java.awt.MediaTracker#isErrorID(int)
  495        */
  496       public boolean checkID(int id) {
  497           return checkID(id, false, true);
  498       }
  499   
  500       /**
  501        * Checks to see if all images tracked by this media tracker that
  502        * are tagged with the specified identifier have finished loading.
  503        * <p>
  504        * If the value of the <code>load</code> flag is <code>true</code>,
  505        * then this method starts loading any images that are not yet
  506        * being loaded.
  507        * <p>
  508        * If there is an error while loading or scaling an image, then that
  509        * image is considered to have finished loading. Use the
  510        * <code>isErrorAny</code> or <code>isErrorID</code> methods to
  511        * check for errors.
  512        * @param       id       the identifier of the images to check
  513        * @param       load     if <code>true</code>, start loading any
  514        *                       images that are not yet being loaded
  515        * @return      <code>true</code> if all images have finished loading,
  516        *                       have been aborted, or have encountered
  517        *                       an error; <code>false</code> otherwise
  518        * @see         java.awt.MediaTracker#checkID(int, boolean)
  519        * @see         java.awt.MediaTracker#checkAll()
  520        * @see         java.awt.MediaTracker#isErrorAny()
  521        * @see         java.awt.MediaTracker#isErrorID(int)
  522        */
  523       public boolean checkID(int id, boolean load) {
  524           return checkID(id, load, true);
  525       }
  526   
  527       private synchronized boolean checkID(int id, boolean load, boolean verify)
  528       {
  529           MediaEntry cur = head;
  530           boolean done = true;
  531           while (cur != null) {
  532               if (cur.getID() == id
  533                   && (cur.getStatus(load, verify) & DONE) == 0)
  534               {
  535                   done = false;
  536               }
  537               cur = cur.next;
  538           }
  539           return done;
  540       }
  541   
  542       /**
  543        * Checks the error status of all of the images tracked by this
  544        * media tracker with the specified identifier.
  545        * @param        id   the identifier of the images to check
  546        * @return       <code>true</code> if any of the images with the
  547        *                          specified identifier had an error during
  548        *                          loading; <code>false</code> otherwise
  549        * @see          java.awt.MediaTracker#isErrorAny
  550        * @see          java.awt.MediaTracker#getErrorsID
  551        */
  552       public synchronized boolean isErrorID(int id) {
  553           MediaEntry cur = head;
  554           while (cur != null) {
  555               if (cur.getID() == id
  556                   && (cur.getStatus(false, true) & ERRORED) != 0)
  557               {
  558                   return true;
  559               }
  560               cur = cur.next;
  561           }
  562           return false;
  563       }
  564   
  565       /**
  566        * Returns a list of media with the specified ID that
  567        * have encountered an error.
  568        * @param       id   the identifier of the images to check
  569        * @return      an array of media objects tracked by this media
  570        *                       tracker with the specified identifier
  571        *                       that have encountered an error, or
  572        *                       <code>null</code> if there are none with errors
  573        * @see         java.awt.MediaTracker#isErrorID
  574        * @see         java.awt.MediaTracker#isErrorAny
  575        * @see         java.awt.MediaTracker#getErrorsAny
  576        */
  577       public synchronized Object[] getErrorsID(int id) {
  578           MediaEntry cur = head;
  579           int numerrors = 0;
  580           while (cur != null) {
  581               if (cur.getID() == id
  582                   && (cur.getStatus(false, true) & ERRORED) != 0)
  583               {
  584                   numerrors++;
  585               }
  586               cur = cur.next;
  587           }
  588           if (numerrors == 0) {
  589               return null;
  590           }
  591           Object errors[] = new Object[numerrors];
  592           cur = head;
  593           numerrors = 0;
  594           while (cur != null) {
  595               if (cur.getID() == id
  596                   && (cur.getStatus(false, false) & ERRORED) != 0)
  597               {
  598                   errors[numerrors++] = cur.getMedia();
  599               }
  600               cur = cur.next;
  601           }
  602           return errors;
  603       }
  604   
  605       /**
  606        * Starts loading all images tracked by this media tracker with the
  607        * specified identifier. This method waits until all the images with
  608        * the specified identifier have finished loading.
  609        * <p>
  610        * If there is an error while loading or scaling an image, then that
  611        * image is considered to have finished loading. Use the
  612        * <code>isErrorAny</code> and <code>isErrorID</code> methods to
  613        * check for errors.
  614        * @param         id   the identifier of the images to check
  615        * @see           java.awt.MediaTracker#waitForAll
  616        * @see           java.awt.MediaTracker#isErrorAny()
  617        * @see           java.awt.MediaTracker#isErrorID(int)
  618        * @exception     InterruptedException  if any thread has
  619        *                          interrupted this thread.
  620        */
  621       public void waitForID(int id) throws InterruptedException {
  622           waitForID(id, 0);
  623       }
  624   
  625       /**
  626        * Starts loading all images tracked by this media tracker with the
  627        * specified identifier. This method waits until all the images with
  628        * the specified identifier have finished loading, or until the
  629        * length of time specified in milliseconds by the <code>ms</code>
  630        * argument has passed.
  631        * <p>
  632        * If there is an error while loading or scaling an image, then that
  633        * image is considered to have finished loading. Use the
  634        * <code>statusID</code>, <code>isErrorID</code>, and
  635        * <code>isErrorAny</code> methods to check for errors.
  636        * @param         id   the identifier of the images to check
  637        * @param         ms   the length of time, in milliseconds, to wait
  638        *                           for the loading to complete
  639        * @see           java.awt.MediaTracker#waitForAll
  640        * @see           java.awt.MediaTracker#waitForID(int)
  641        * @see           java.awt.MediaTracker#statusID
  642        * @see           java.awt.MediaTracker#isErrorAny()
  643        * @see           java.awt.MediaTracker#isErrorID(int)
  644        * @exception     InterruptedException  if any thread has
  645        *                          interrupted this thread.
  646        */
  647       public synchronized boolean waitForID(int id, long ms)
  648           throws InterruptedException
  649       {
  650           long end = System.currentTimeMillis() + ms;
  651           boolean first = true;
  652           while (true) {
  653               int status = statusID(id, first, first);
  654               if ((status & LOADING) == 0) {
  655                   return (status == COMPLETE);
  656               }
  657               first = false;
  658               long timeout;
  659               if (ms == 0) {
  660                   timeout = 0;
  661               } else {
  662                   timeout = end - System.currentTimeMillis();
  663                   if (timeout <= 0) {
  664                       return false;
  665                   }
  666               }
  667               wait(timeout);
  668           }
  669       }
  670   
  671       /**
  672        * Calculates and returns the bitwise inclusive <b>OR</b> of the
  673        * status of all media with the specified identifier that are
  674        * tracked by this media tracker.
  675        * <p>
  676        * Possible flags defined by the
  677        * <code>MediaTracker</code> class are <code>LOADING</code>,
  678        * <code>ABORTED</code>, <code>ERRORED</code>, and
  679        * <code>COMPLETE</code>. An image that hasn't started
  680        * loading has zero as its status.
  681        * <p>
  682        * If the value of <code>load</code> is <code>true</code>, then
  683        * this method starts loading any images that are not yet being loaded.
  684        * @param        id   the identifier of the images to check
  685        * @param        load   if <code>true</code>, start loading
  686        *                            any images that are not yet being loaded
  687        * @return       the bitwise inclusive <b>OR</b> of the status of
  688        *                            all of the media with the specified
  689        *                            identifier that are being tracked
  690        * @see          java.awt.MediaTracker#statusAll(boolean)
  691        * @see          java.awt.MediaTracker#LOADING
  692        * @see          java.awt.MediaTracker#ABORTED
  693        * @see          java.awt.MediaTracker#ERRORED
  694        * @see          java.awt.MediaTracker#COMPLETE
  695        */
  696       public int statusID(int id, boolean load) {
  697           return statusID(id, load, true);
  698       }
  699   
  700       private synchronized int statusID(int id, boolean load, boolean verify) {
  701           MediaEntry cur = head;
  702           int status = 0;
  703           while (cur != null) {
  704               if (cur.getID() == id) {
  705                   status = status | cur.getStatus(load, verify);
  706               }
  707               cur = cur.next;
  708           }
  709           return status;
  710       }
  711   
  712       /**
  713        * Removes the specified image from this media tracker.
  714        * All instances of the specified image are removed,
  715        * regardless of scale or ID.
  716        * @param   image     the image to be removed
  717        * @see     java.awt.MediaTracker#removeImage(java.awt.Image, int)
  718        * @see     java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int)
  719        * @since   JDK1.1
  720        */
  721       public synchronized void removeImage(Image image) {
  722           MediaEntry cur = head;
  723           MediaEntry prev = null;
  724           while (cur != null) {
  725               MediaEntry next = cur.next;
  726               if (cur.getMedia() == image) {
  727                   if (prev == null) {
  728                       head = next;
  729                   } else {
  730                       prev.next = next;
  731                   }
  732                   cur.cancel();
  733               } else {
  734                   prev = cur;
  735               }
  736               cur = next;
  737           }
  738           notifyAll();    // Notify in case remaining images are "done".
  739       }
  740   
  741       /**
  742        * Removes the specified image from the specified tracking
  743        * ID of this media tracker.
  744        * All instances of <code>Image</code> being tracked
  745        * under the specified ID are removed regardless of scale.
  746        * @param      image the image to be removed
  747        * @param      id the tracking ID frrom which to remove the image
  748        * @see        java.awt.MediaTracker#removeImage(java.awt.Image)
  749        * @see        java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int)
  750        * @since      JDK1.1
  751        */
  752       public synchronized void removeImage(Image image, int id) {
  753           MediaEntry cur = head;
  754           MediaEntry prev = null;
  755           while (cur != null) {
  756               MediaEntry next = cur.next;
  757               if (cur.getID() == id && cur.getMedia() == image) {
  758                   if (prev == null) {
  759                       head = next;
  760                   } else {
  761                       prev.next = next;
  762                   }
  763                   cur.cancel();
  764               } else {
  765                   prev = cur;
  766               }
  767               cur = next;
  768           }
  769           notifyAll();    // Notify in case remaining images are "done".
  770       }
  771   
  772       /**
  773        * Removes the specified image with the specified
  774        * width, height, and ID from this media tracker.
  775        * Only the specified instance (with any duplicates) is removed.
  776        * @param   image the image to be removed
  777        * @param   id the tracking ID from which to remove the image
  778        * @param   width the width to remove (-1 for unscaled)
  779        * @param   height the height to remove (-1 for unscaled)
  780        * @see     java.awt.MediaTracker#removeImage(java.awt.Image)
  781        * @see     java.awt.MediaTracker#removeImage(java.awt.Image, int)
  782        * @since   JDK1.1
  783        */
  784       public synchronized void removeImage(Image image, int id,
  785                                            int width, int height) {
  786           MediaEntry cur = head;
  787           MediaEntry prev = null;
  788           while (cur != null) {
  789               MediaEntry next = cur.next;
  790               if (cur.getID() == id && cur instanceof ImageMediaEntry
  791                   && ((ImageMediaEntry) cur).matches(image, width, height))
  792               {
  793                   if (prev == null) {
  794                       head = next;
  795                   } else {
  796                       prev.next = next;
  797                   }
  798                   cur.cancel();
  799               } else {
  800                   prev = cur;
  801               }
  802               cur = next;
  803           }
  804           notifyAll();    // Notify in case remaining images are "done".
  805       }
  806   
  807       synchronized void setDone() {
  808           notifyAll();
  809       }
  810   }
  811   
  812   abstract class MediaEntry {
  813       MediaTracker tracker;
  814       int ID;
  815       MediaEntry next;
  816   
  817       int status;
  818       boolean cancelled;
  819   
  820       MediaEntry(MediaTracker mt, int id) {
  821           tracker = mt;
  822           ID = id;
  823       }
  824   
  825       abstract Object getMedia();
  826   
  827       static MediaEntry insert(MediaEntry head, MediaEntry me) {
  828           MediaEntry cur = head;
  829           MediaEntry prev = null;
  830           while (cur != null) {
  831               if (cur.ID > me.ID) {
  832                   break;
  833               }
  834               prev = cur;
  835               cur = cur.next;
  836           }
  837           me.next = cur;
  838           if (prev == null) {
  839               head = me;
  840           } else {
  841               prev.next = me;
  842           }
  843           return head;
  844       }
  845   
  846       int getID() {
  847           return ID;
  848       }
  849   
  850       abstract void startLoad();
  851   
  852       void cancel() {
  853           cancelled = true;
  854       }
  855   
  856       static final int LOADING = MediaTracker.LOADING;
  857       static final int ABORTED = MediaTracker.ABORTED;
  858       static final int ERRORED = MediaTracker.ERRORED;
  859       static final int COMPLETE = MediaTracker.COMPLETE;
  860   
  861       static final int LOADSTARTED = (LOADING | ERRORED | COMPLETE);
  862       static final int DONE = (ABORTED | ERRORED | COMPLETE);
  863   
  864       synchronized int getStatus(boolean doLoad, boolean doVerify) {
  865           if (doLoad && ((status & LOADSTARTED) == 0)) {
  866               status = (status & ~ABORTED) | LOADING;
  867               startLoad();
  868           }
  869           return status;
  870       }
  871   
  872       void setStatus(int flag) {
  873           synchronized (this) {
  874               status = flag;
  875           }
  876           tracker.setDone();
  877       }
  878   }
  879   
  880   class ImageMediaEntry extends MediaEntry implements ImageObserver,
  881   java.io.Serializable {
  882       Image image;
  883       int width;
  884       int height;
  885   
  886       /*
  887        * JDK 1.1 serialVersionUID
  888        */
  889       private static final long serialVersionUID = 4739377000350280650L;
  890   
  891       ImageMediaEntry(MediaTracker mt, Image img, int c, int w, int h) {
  892           super(mt, c);
  893           image = img;
  894           width = w;
  895           height = h;
  896       }
  897   
  898       boolean matches(Image img, int w, int h) {
  899           return (image == img && width == w && height == h);
  900       }
  901   
  902       Object getMedia() {
  903           return image;
  904       }
  905   
  906       synchronized int getStatus(boolean doLoad, boolean doVerify) {
  907           if (doVerify) {
  908               int flags = tracker.target.checkImage(image, width, height, null);
  909               int s = parseflags(flags);
  910               if (s == 0) {
  911                   if ((status & (ERRORED | COMPLETE)) != 0) {
  912                       setStatus(ABORTED);
  913                   }
  914               } else if (s != status) {
  915                   setStatus(s);
  916               }
  917           }
  918           return super.getStatus(doLoad, doVerify);
  919       }
  920   
  921       void startLoad() {
  922           if (tracker.target.prepareImage(image, width, height, this)) {
  923               setStatus(COMPLETE);
  924           }
  925       }
  926   
  927       int parseflags(int infoflags) {
  928           if ((infoflags & ERROR) != 0) {
  929               return ERRORED;
  930           } else if ((infoflags & ABORT) != 0) {
  931               return ABORTED;
  932           } else if ((infoflags & (ALLBITS | FRAMEBITS)) != 0) {
  933               return COMPLETE;
  934           }
  935           return 0;
  936       }
  937   
  938       public boolean imageUpdate(Image img, int infoflags,
  939                                  int x, int y, int w, int h) {
  940           if (cancelled) {
  941               return false;
  942           }
  943           int s = parseflags(infoflags);
  944           if (s != 0 && s != status) {
  945               setStatus(s);
  946           }
  947           return ((status & LOADING) != 0);
  948       }
  949   }

Home » openjdk-7 » java » awt » [javadoc | source]