mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			699 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			699 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* MediaTracker.java -- Class used for keeping track of images
 | |
|    Copyright (C) 1999, 2002, 2004, 2005  Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| 
 | |
| package java.awt;
 | |
| 
 | |
| import java.awt.image.ImageObserver;
 | |
| import java.util.ArrayList;
 | |
| 
 | |
| /**
 | |
|   * This class is used for keeping track of the status of various media
 | |
|   * objects.
 | |
|   *
 | |
|   * Media objects are tracked by assigning them an ID. It is possible
 | |
|   * to assign the same ID to mutliple objects, effectivly grouping them
 | |
|   * together. In this case the status flags ({@link #statusID}) and error flag
 | |
|   * (@link #isErrorID} and {@link #getErrorsID}) are ORed together. This
 | |
|   * means that you cannot say exactly which media object has which status,
 | |
|   * at most you can say that there <em>are</em> certain media objects with
 | |
|   * some certain status.
 | |
|   * 
 | |
|   * At the moment only images are supported by this class.
 | |
|   *
 | |
|   * @author Aaron M. Renn (arenn@urbanophile.com)
 | |
|   * @author Bryce McKinlay
 | |
|   */
 | |
| public class MediaTracker implements java.io.Serializable
 | |
| {
 | |
|   /** Indicates that the media is still loading. */
 | |
|   public static final int LOADING = 1 << 0;
 | |
| 
 | |
|   /** Indicates that the loading operation has been aborted. */
 | |
|   public static final int ABORTED = 1 << 1;
 | |
| 
 | |
|   /** Indicates that an error has occured during loading of the media. */
 | |
|   public static final int ERRORED = 1 << 2;
 | |
| 
 | |
|   /** Indicates that the media has been successfully and completely loaded. */
 | |
|   public static final int COMPLETE = 1 << 3;
 | |
| 
 | |
|   /** The component on which the media is eventually been drawn. */
 | |
|   Component target;
 | |
| 
 | |
|   /** The head of the linked list of tracked media objects. */
 | |
|   MediaEntry head;
 | |
| 
 | |
|   /** Our serialVersionUID for serialization. */
 | |
|   static final long serialVersionUID = -483174189758638095L;
 | |
| 
 | |
|   /**
 | |
|    * This represents a media object that is tracked by a MediaTracker.
 | |
|    * It also implements a simple linked list.
 | |
|    */
 | |
|   // FIXME: The serialized form documentation says MediaEntry is a 
 | |
|   // serializable field, but the serialized form of MediaEntry itself
 | |
|   // doesn't appear to be documented.
 | |
|   class MediaEntry implements ImageObserver
 | |
|   {
 | |
|     /** The ID of the media object. */
 | |
|     int id;
 | |
| 
 | |
|     /** The media object. (only images are supported ATM). */
 | |
|     Image image;
 | |
| 
 | |
|     /** The link to the next entry in the list. */
 | |
|     MediaEntry next;
 | |
| 
 | |
|     /** The tracking status. */
 | |
|     int status;
 | |
| 
 | |
|     /** The width of the image. */
 | |
|     int width;
 | |
| 
 | |
|     /** The height of the image. */
 | |
|     int height;
 | |
|     
 | |
|     /**
 | |
|      * Receives notification from an {@link java.awt.image.ImageProducer}
 | |
|      * that more data of the image is available.
 | |
|      *
 | |
|      * @param img the image that is updated
 | |
|      * @param flags flags from the ImageProducer that indicate the status
 | |
|      *        of the loading process
 | |
|      * @param x the X coordinate of the upper left corner of the image
 | |
|      * @param y the Y coordinate of the upper left corner of the image
 | |
|      * @param width the width of the image
 | |
|      * @param height the height of the image
 | |
|      *
 | |
|      * @return <code>true</code> if more data is needed, <code>false</code>
 | |
|      *         otherwise
 | |
|      *
 | |
|      * @see java.awt.image.ImageObserver
 | |
|      */
 | |
|     public boolean imageUpdate(Image img, int flags, int x, int y, 
 | |
|                                int width, int height)
 | |
|     {
 | |
|       if ((flags & ABORT) != 0)
 | |
|         status = ABORTED;
 | |
|       else if ((flags & ERROR) != 0)
 | |
|         status = ERRORED;
 | |
|       else if ((flags & ALLBITS) != 0)
 | |
|         status = COMPLETE;
 | |
|       else
 | |
|         status = 0;
 | |
| 
 | |
|       synchronized (MediaTracker.this)
 | |
|         {
 | |
|           MediaTracker.this.notifyAll();
 | |
|         }
 | |
| 
 | |
|       // If status is not COMPLETE then we need more updates.
 | |
|       return ((status & (COMPLETE | ERRORED | ABORTED)) == 0);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Constructs a new MediaTracker for the component <code>c</code>. The
 | |
|    * component should be the component that uses the media (i.e. draws it).
 | |
|    *
 | |
|    * @param c the Component that wants to use the media
 | |
|    */
 | |
|   public MediaTracker(Component c)
 | |
|   {
 | |
|     target = c;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds an image to the tracker with the specified <code>ID</code>.
 | |
|    *
 | |
|    * @param image the image to be added
 | |
|    * @param id the ID of the tracker list to which the image is added
 | |
|    */
 | |
|   public void addImage(Image image, int id)
 | |
|   {
 | |
|     MediaEntry e = new MediaEntry();
 | |
|     e.id = id;
 | |
|     e.image = image;
 | |
|     synchronized(this)
 | |
|       {
 | |
|         e.next = head;
 | |
|         head = e;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds an image to the tracker with the specified <code>ID</code>.
 | |
|    * The image is expected to be rendered with the specified width and
 | |
|    * height.
 | |
|    *
 | |
|    * @param image the image to be added
 | |
|    * @param id the ID of the tracker list to which the image is added
 | |
|    * @param width the width of the image
 | |
|    * @param height the height of the image
 | |
|    */
 | |
|   public void addImage(Image image, int id, int width, int height)
 | |
|   {
 | |
|     MediaEntry e = new MediaEntry();
 | |
|     e.id = id;
 | |
|     e.image = image;
 | |
|     e.width = width;
 | |
|     e.height = height;
 | |
|     synchronized(this)
 | |
|       {
 | |
|         e.next = head;
 | |
|         head = e;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if all media objects have finished loading, i.e. are
 | |
|    * {@link #COMPLETE}, {@link #ABORTED} or {@link #ERRORED}.
 | |
|    *
 | |
|    * If the media objects are not already loading, a call to this
 | |
|    * method does <em>not</em> start loading. This is equivalent to
 | |
|    * a call to <code>checkAll(false)</code>.
 | |
|    *
 | |
|    * @return if all media objects have finished loading either by beeing
 | |
|    *         complete, have been aborted or errored.
 | |
|    */
 | |
|   public boolean checkAll()
 | |
|   {
 | |
|     return checkAll(false);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if all media objects have finished loading, i.e. are
 | |
|    * {@link #COMPLETE}, {@link #ABORTED} or {@link #ERRORED}.
 | |
|    *
 | |
|    * If the media objects are not already loading, and <code>load</code>
 | |
|    * is <code>true</code> then a call to this
 | |
|    * method starts loading the media objects.
 | |
|    *
 | |
|    * @param load if <code>true</code> this method starts loading objects
 | |
|    *        that are not already loading
 | |
|    *
 | |
|    * @return if all media objects have finished loading either by beeing
 | |
|    *         complete, have been aborted or errored.
 | |
|    */
 | |
|   public boolean checkAll(boolean load)
 | |
|   {
 | |
|     MediaEntry e = head;
 | |
|     boolean result = true;
 | |
|     
 | |
|     while (e != null)
 | |
|       {
 | |
|         if ((e.status & (COMPLETE | ERRORED | ABORTED)) == 0)
 | |
|           {
 | |
|             if (load && ((e.status & LOADING) == 0))
 | |
|               {
 | |
| 		if (target.prepareImage(e.image, e))
 | |
| 		  e.status = COMPLETE;
 | |
| 		else
 | |
| 		  {
 | |
| 		    e.status = LOADING;
 | |
| 		    int flags = target.checkImage(e.image, e);
 | |
| 		    if ((flags & ImageObserver.ABORT) != 0)
 | |
| 		      e.status = ABORTED;
 | |
| 		    else if ((flags & ImageObserver.ERROR) != 0)
 | |
| 		      e.status = ERRORED;
 | |
| 		    else if ((flags & ImageObserver.ALLBITS) != 0)
 | |
| 		      e.status = COMPLETE;
 | |
| 		  }
 | |
| 		boolean complete = (e.status
 | |
| 				    & (COMPLETE | ABORTED | ERRORED)) != 0;
 | |
| 		if (!complete)
 | |
| 		  result = false;
 | |
| 	      }
 | |
|             else
 | |
|               result = false;
 | |
|           }
 | |
|         e = e.next;
 | |
|       }
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if any of the registered media objects has encountered an error
 | |
|    * during loading.
 | |
|    *
 | |
|    * @return <code>true</code> if at least one media object has encountered
 | |
|    *         an error during loading, <code>false</code> otherwise
 | |
|    *
 | |
|    */
 | |
|   public boolean isErrorAny()
 | |
|   {
 | |
|     MediaEntry e = head;    
 | |
|     while (e != null)
 | |
|       {
 | |
|         if ((e.status & ERRORED) != 0)
 | |
|           return true;
 | |
|         e = e.next;
 | |
|       }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns all media objects that have encountered errors during loading.
 | |
|    *
 | |
|    * @return an array of all media objects that have encountered errors
 | |
|    *         or <code>null</code> if there were no errors at all
 | |
|    */
 | |
|   public Object[] getErrorsAny()
 | |
|   {
 | |
|     MediaEntry e = head;
 | |
|     ArrayList result = null;
 | |
|     while (e != null)
 | |
|       {
 | |
|         if ((e.status & ERRORED) != 0)
 | |
|           {
 | |
|             if (result == null)
 | |
|               result = new ArrayList();
 | |
|             result.add(e.image);
 | |
|           }
 | |
|         e = e.next;
 | |
|       }
 | |
|     if (result == null)
 | |
|       return null;
 | |
|     else
 | |
|       return result.toArray();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Waits for all media objects to finish loading, either by completing
 | |
|    * successfully or by aborting or encountering an error.
 | |
|    *
 | |
|    * @throws InterruptedException if another thread interrupted the
 | |
|    *         current thread while waiting
 | |
|    */
 | |
|   public void waitForAll() throws InterruptedException
 | |
|   {
 | |
|     synchronized (this)
 | |
|     {
 | |
|       while (checkAll(true) == false)
 | |
|         wait();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Waits for all media objects to finish loading, either by completing
 | |
|    * successfully or by aborting or encountering an error.
 | |
|    *
 | |
|    * This method waits at most <code>ms</code> milliseconds. If the
 | |
|    * media objects have not completed loading within this timeframe, this
 | |
|    * method returns <code>false</code>, otherwise <code>true</code>.
 | |
|    *
 | |
|    * @param ms timeframe in milliseconds to wait for the media objects to
 | |
|    *        finish
 | |
|    *
 | |
|    * @return <code>true</code> if all media objects have successfully loaded
 | |
|    *         within the timeframe, <code>false</code> otherwise
 | |
|    *
 | |
|    * @throws InterruptedException if another thread interrupted the
 | |
|    *         current thread while waiting
 | |
|    */
 | |
|   public boolean waitForAll(long ms) throws InterruptedException
 | |
|   {
 | |
|     long start = System.currentTimeMillis();
 | |
|     boolean result = checkAll(true);
 | |
|     synchronized (this)
 | |
|     {
 | |
|       while (result == false)
 | |
|         {
 | |
|           wait(ms);
 | |
|           result = checkAll(true);
 | |
|           if ((System.currentTimeMillis() - start) > ms)
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the status flags of all registered media objects ORed together.
 | |
|    * If <code>load</code> is <code>true</code> then media objects that
 | |
|    * are not already loading will be started to load.
 | |
|    *
 | |
|    * @param load if set to <code>true</code> then media objects that are
 | |
|    *        not already loading are started
 | |
|    *
 | |
|    * @return the status flags of all tracked media objects ORed together
 | |
|    */
 | |
|   public int statusAll(boolean load)
 | |
|   {
 | |
|     int result = 0;
 | |
|     MediaEntry e = head;
 | |
|     while (e != null)
 | |
|       {
 | |
|         if (load && e.status == 0)
 | |
|           {
 | |
|             if (target.prepareImage(e.image, e))
 | |
|               e.status = COMPLETE;
 | |
|             else
 | |
| 	      {
 | |
|                 e.status = LOADING;
 | |
|                 int flags = target.checkImage(e.image, e);
 | |
| 		if ((flags & ImageObserver.ABORT) != 0)
 | |
| 		  e.status = ABORTED;
 | |
| 		else if ((flags & ImageObserver.ERROR) != 0)
 | |
| 		  e.status = ERRORED;
 | |
| 		else if ((flags & ImageObserver.ALLBITS) != 0)
 | |
| 		  e.status = COMPLETE;
 | |
| 	      }
 | |
|           }
 | |
|         result |= e.status;
 | |
|         e = e.next;
 | |
|       }
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if the media objects with <code>ID</code> have completed loading.
 | |
|    *
 | |
|    * @param id the ID of the media objects to check
 | |
|    *
 | |
|    * @return <code>true</code> if all media objects with <code>ID</code>
 | |
|    *         have successfully finished
 | |
|    */
 | |
|   public boolean checkID(int id)
 | |
|   {
 | |
|     return checkID(id, false);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Checks if the media objects with <code>ID</code> have completed loading.
 | |
|    * If <code>load</code> is <code>true</code> then media objects that
 | |
|    * are not already loading will be started to load.
 | |
|    *
 | |
|    * @param id the ID of the media objects to check
 | |
|    * @param load if set to <code>true</code> then media objects that are
 | |
|    *        not already loading are started
 | |
|    *
 | |
|    * @return <code>true</code> if all media objects with <code>ID</code>
 | |
|    *         have successfully finished
 | |
|    */
 | |
|   public boolean checkID(int id, boolean load)
 | |
|   {
 | |
|     MediaEntry e = head;
 | |
|     boolean result = true;
 | |
|     
 | |
|     while (e != null)
 | |
|       {
 | |
|         if (e.id == id && ((e.status & (COMPLETE | ABORTED | ERRORED)) == 0))
 | |
|           {
 | |
|             if (load && ((e.status & LOADING) == 0))
 | |
|               {
 | |
|                 e.status = LOADING;
 | |
| 		if (target.prepareImage(e.image, e))
 | |
| 		  e.status = COMPLETE;
 | |
| 		else
 | |
| 		  {
 | |
| 		    int flags = target.checkImage(e.image, e);
 | |
| 		    if ((flags & ImageObserver.ABORT) != 0)
 | |
| 		      e.status = ABORTED;
 | |
| 		    else if ((flags & ImageObserver.ERROR) != 0)
 | |
| 		      e.status = ERRORED;
 | |
| 		    else if ((flags & ImageObserver.ALLBITS) != 0)
 | |
| 		      e.status = COMPLETE;
 | |
| 		  }
 | |
| 		boolean complete = (e.status
 | |
| 				    & (COMPLETE | ABORTED | ERRORED)) != 0;
 | |
| 		if (!complete)
 | |
| 		  result = false;
 | |
|               }
 | |
|             else
 | |
|               result = false;
 | |
|           }
 | |
|         e = e.next;
 | |
|       }
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns <code>true</code> if any of the media objects with <code>ID</code>
 | |
|    * have encountered errors during loading, false otherwise.
 | |
|    *
 | |
|    * @param id the ID of the media objects to check
 | |
|    *
 | |
|    * @return <code>true</code> if any of the media objects with <code>ID</code>
 | |
|    *         have encountered errors during loading, false otherwise
 | |
|    */
 | |
|   public boolean isErrorID(int id)
 | |
|   {
 | |
|     MediaEntry e = head;    
 | |
|     while (e != null)
 | |
|       {
 | |
|         if (e.id == id && ((e.status & ERRORED) != 0))
 | |
|           return true;
 | |
|         e = e.next;
 | |
|       }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns all media objects with the specified ID that have encountered
 | |
|    * an error.
 | |
|    *
 | |
|    * @param id the ID of the media objects to check
 | |
|    *
 | |
|    * @return an array of all media objects  with the specified ID that
 | |
|    *         have encountered an error
 | |
|    */
 | |
|   public Object[] getErrorsID(int id)
 | |
|   {
 | |
|     MediaEntry e = head;
 | |
|     ArrayList result = null;
 | |
|     while (e != null)
 | |
|       {
 | |
|         if (e.id == id && ((e.status & ERRORED) != 0))
 | |
|           {
 | |
|             if (result == null)
 | |
|               result = new ArrayList();
 | |
|             result.add(e.image);
 | |
|           }
 | |
|         e = e.next;
 | |
|       }
 | |
|     if (result == null)
 | |
|       return null;
 | |
|     else
 | |
|       return result.toArray();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Waits for all media objects with the specified ID to finish loading,
 | |
|    * either by completing successfully or by aborting or encountering an error.
 | |
|    *
 | |
|    * @param id the ID of the media objects to wait for
 | |
|    *
 | |
|    * @throws InterruptedException if another thread interrupted the
 | |
|    *         current thread while waiting
 | |
|    */
 | |
|   public void waitForID(int id) throws InterruptedException
 | |
|   {
 | |
|     MediaEntry e = head;
 | |
|     synchronized (this)
 | |
|     {
 | |
|       while (checkID (id, true) == false)
 | |
|         wait();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Waits for all media objects with the specified ID to finish loading,
 | |
|    * either by completing successfully or by aborting or encountering an error.
 | |
|    *
 | |
|    * This method waits at most <code>ms</code> milliseconds. If the
 | |
|    * media objects have not completed loading within this timeframe, this
 | |
|    * method returns <code>false</code>, otherwise <code>true</code>.
 | |
|    *
 | |
|    * @param id the ID of the media objects to wait for
 | |
|    * @param ms timeframe in milliseconds to wait for the media objects to
 | |
|    *        finish
 | |
|    *
 | |
|    * @return <code>true</code> if all media objects have successfully loaded
 | |
|    *         within the timeframe, <code>false</code> otherwise
 | |
|    *
 | |
|    * @throws InterruptedException if another thread interrupted the
 | |
|    *         current thread while waiting
 | |
|    */
 | |
|   public boolean waitForID(int id, long ms) throws InterruptedException
 | |
|   {
 | |
|     MediaEntry e = head;
 | |
|     long start = System.currentTimeMillis();
 | |
|     boolean result = checkID(id, true);
 | |
| 
 | |
|     synchronized (this)
 | |
|     {
 | |
|       while (result == false)
 | |
|         {
 | |
|           wait(ms);
 | |
|           result = checkID(id, true);
 | |
|           if ((System.currentTimeMillis() - start) > ms)
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the status flags of the media objects with the specified ID
 | |
|    * ORed together.
 | |
|    *
 | |
|    * If <code>load</code> is <code>true</code> then media objects that
 | |
|    * are not already loading will be started to load.
 | |
|    *
 | |
|    * @param load if set to <code>true</code> then media objects that are
 | |
|    *        not already loading are started
 | |
|    *
 | |
|    * @return the status flags of all tracked media objects ORed together
 | |
|    */
 | |
|   public int statusID(int id, boolean load)
 | |
|   {
 | |
|     int result = 0;
 | |
|     MediaEntry e = head;
 | |
|     while (e != null)
 | |
|       {
 | |
|         if (e.id == id)
 | |
|           {
 | |
|             if (load && e.status == 0)
 | |
|               {
 | |
| 		if (target.prepareImage(e.image, e))
 | |
|                   e.status = COMPLETE;
 | |
| 		else
 | |
| 		  {
 | |
| 		    e.status = LOADING;
 | |
| 		    int flags = target.checkImage(e.image, e);
 | |
| 		    if ((flags & ImageObserver.ABORT) != 0)
 | |
| 		      e.status = ABORTED;
 | |
| 		    else if ((flags & ImageObserver.ERROR) != 0)
 | |
| 		      e.status = ERRORED;
 | |
| 		    else if ((flags & ImageObserver.ALLBITS) != 0)
 | |
| 		      e.status = COMPLETE;
 | |
| 		  }
 | |
|               }
 | |
|             result |= e.status;
 | |
|           }
 | |
|         e = e.next;
 | |
|       }
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes an image from this MediaTracker.
 | |
|    *
 | |
|    * @param image the image to be removed
 | |
|    */
 | |
|   public void removeImage(Image image)
 | |
|   {
 | |
|     synchronized (this)
 | |
|       {
 | |
|         MediaEntry e = head;
 | |
|         MediaEntry prev = null;
 | |
|         while (e != null)
 | |
|           {
 | |
|             if (e.image == image)
 | |
|               {
 | |
|                 if (prev == null)
 | |
|                   head = e.next;
 | |
|                 else
 | |
|                   prev.next = e.next;
 | |
|               }
 | |
|             else
 | |
|               prev = e;
 | |
|             e = e.next;
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes an image with the specified ID from this MediaTracker.
 | |
|    *
 | |
|    * @param image the image to be removed
 | |
|    */
 | |
|   public void removeImage(Image image, int id)
 | |
|   {
 | |
|     synchronized (this)
 | |
|       {
 | |
|         MediaEntry e = head;
 | |
|         MediaEntry prev = null;
 | |
|         while (e != null)
 | |
|           {
 | |
|             if (e.id == id && e.image == image)
 | |
|               {
 | |
|                 if (prev == null)
 | |
|                   head = e.next;
 | |
|                 else
 | |
|                   prev.next = e.next;
 | |
|               }
 | |
|             else
 | |
|               prev = e;
 | |
|             e = e.next;
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes an image with the specified ID and scale from this MediaTracker.
 | |
|    *
 | |
|    * @param image the image to be removed
 | |
|    */
 | |
|   public void removeImage(Image image, int id, int width, int height)
 | |
|   {
 | |
|     synchronized (this)
 | |
|       {
 | |
|         MediaEntry e = head;
 | |
|         MediaEntry prev = null;
 | |
|         while (e != null)
 | |
|           {
 | |
|             if (e.id == id && e.image == image
 | |
|                 && e.width == width && e.height == height)
 | |
|               {
 | |
|                 if (prev == null)
 | |
|                   head = e.next;
 | |
|                 else
 | |
|                   prev.next = e.next;
 | |
|               }
 | |
|             else
 | |
|               prev = e;
 | |
|             e = e.next;
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| }
 |