KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > MediaTracker


1 /*
2  * @(#)MediaTracker.java 1.42 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt;
9
10 import java.awt.Component JavaDoc;
11 import java.awt.Image JavaDoc;
12 import java.awt.Graphics JavaDoc;
13 import java.awt.image.ImageObserver JavaDoc;
14
15 /**
16  * The <code>MediaTracker</code> class is a utility class to track
17  * the status of a number of media objects. Media objects could
18  * include audio clips as well as images, though currently only
19  * images are supported.
20  * <p>
21  * To use a media tracker, create an instance of
22  * <code>MediaTracker</code> and call its <code>addImage</code>
23  * method for each image to be tracked. In addition, each image can
24  * be assigned a unique identifier. This identifier controls the
25  * priority order in which the images are fetched. It can also be used
26  * to identify unique subsets of the images that can be waited on
27  * independently. Images with a lower ID are loaded in preference to
28  * those with a higher ID number.
29  *
30  * <p>
31  *
32  * Tracking an animated image
33  * might not always be useful
34  * due to the multi-part nature of animated image
35  * loading and painting,
36  * but it is supported.
37  * <code>MediaTracker</code> treats an animated image
38  * as completely loaded
39  * when the first frame is completely loaded.
40  * At that point, the <code>MediaTracker</code>
41  * signals any waiters
42  * that the image is completely loaded.
43  * If no <code>ImageObserver</code>s are observing the image
44  * when the first frame has finished loading,
45  * the image might flush itself
46  * to conserve resources
47  * (see {@link Image#flush()}).
48  *
49  * <p>
50  * Here is an example of using <code>MediaTracker</code>:
51  * <p>
52  * <hr><blockquote><pre>
53  * import java.applet.Applet;
54  * import java.awt.Color;
55  * import java.awt.Image;
56  * import java.awt.Graphics;
57  * import java.awt.MediaTracker;
58  *
59  * public class ImageBlaster extends Applet implements Runnable {
60  * MediaTracker tracker;
61  * Image bg;
62  * Image anim[] = new Image[5];
63  * int index;
64  * Thread animator;
65  *
66  * // Get the images for the background (id == 0)
67  * // and the animation frames (id == 1)
68  * // and add them to the MediaTracker
69  * public void init() {
70  * tracker = new MediaTracker(this);
71  * bg = getImage(getDocumentBase(),
72  * "images/background.gif");
73  * tracker.addImage(bg, 0);
74  * for (int i = 0; i < 5; i++) {
75  * anim[i] = getImage(getDocumentBase(),
76  * "images/anim"+i+".gif");
77  * tracker.addImage(anim[i], 1);
78  * }
79  * }
80  *
81  * // Start the animation thread.
82  * public void start() {
83  * animator = new Thread(this);
84  * animator.start();
85  * }
86  *
87  * // Stop the animation thread.
88  * public void stop() {
89  * animator = null;
90  * }
91  *
92  * // Run the animation thread.
93  * // First wait for the background image to fully load
94  * // and paint. Then wait for all of the animation
95  * // frames to finish loading. Finally, loop and
96  * // increment the animation frame index.
97  * public void run() {
98  * try {
99  * tracker.waitForID(0);
100  * tracker.waitForID(1);
101  * } catch (InterruptedException e) {
102  * return;
103  * }
104  * Thread me = Thread.currentThread();
105  * while (animator == me) {
106  * try {
107  * Thread.sleep(100);
108  * } catch (InterruptedException e) {
109  * break;
110  * }
111  * synchronized (this) {
112  * index++;
113  * if (index >= anim.length) {
114  * index = 0;
115  * }
116  * }
117  * repaint();
118  * }
119  * }
120  *
121  * // The background image fills the frame so we
122  * // don't need to clear the applet on repaints.
123  * // Just call the paint method.
124  * public void update(Graphics g) {
125  * paint(g);
126  * }
127  *
128  * // Paint a large red rectangle if there are any errors
129  * // loading the images. Otherwise always paint the
130  * // background so that it appears incrementally as it
131  * // is loading. Finally, only paint the current animation
132  * // frame if all of the frames (id == 1) are done loading,
133  * // so that we don't get partial animations.
134  * public void paint(Graphics g) {
135  * if ((tracker.statusAll(false) & MediaTracker.ERRORED) != 0) {
136  * g.setColor(Color.red);
137  * g.fillRect(0, 0, size().width, size().height);
138  * return;
139  * }
140  * g.drawImage(bg, 0, 0, this);
141  * if (tracker.statusID(1, false) == MediaTracker.COMPLETE) {
142  * g.drawImage(anim[index], 10, 10, this);
143  * }
144  * }
145  * }
146  * </pre></blockquote><hr>
147  *
148  * @version 1.42, 12/19/03
149  * @author Jim Graham
150  * @since JDK1.0
151  */

152 public class MediaTracker implements java.io.Serializable JavaDoc {
153     
154     /**
155      * A given <code>Component</code> that will be
156      * tracked by a media tracker where the image will
157      * eventually be drawn.
158      *
159      * @serial
160      * @see #MediaTracker(Component)
161      */

162     Component JavaDoc target;
163     /**
164      * The head of the list of <code>Images</code> that is being
165      * tracked by the <code>MediaTracker</code>.
166      *
167      * @serial
168      * @see #addImage(Image, int)
169      * @see #removeImage(Image)
170      */

171     MediaEntry head;
172
173     /*
174      * JDK 1.1 serialVersionUID
175      */

176     private static final long serialVersionUID = -483174189758638095L;
177
178     /**
179      * Creates a media tracker to track images for a given component.
180      * @param comp the component on which the images
181      * will eventually be drawn
182      */

183     public MediaTracker(Component JavaDoc comp) {
184     target = comp;
185     }
186
187     /**
188      * Adds an image to the list of images being tracked by this media
189      * tracker. The image will eventually be rendered at its default
190      * (unscaled) size.
191      * @param image the image to be tracked
192      * @param id an identifier used to track this image
193      */

194     public void addImage(Image JavaDoc image, int id) {
195     addImage(image, id, -1, -1);
196     }
197
198     /**
199      * Adds a scaled image to the list of images being tracked
200      * by this media tracker. The image will eventually be
201      * rendered at the indicated width and height.
202      *
203      * @param image the image to be tracked
204      * @param id an identifier that can be used to track this image
205      * @param w the width at which the image is rendered
206      * @param h the height at which the image is rendered
207      */

208     public synchronized void addImage(Image JavaDoc image, int id, int w, int h) {
209     head = MediaEntry.insert(head,
210                  new ImageMediaEntry(this, image, id, w, h));
211     }
212
213     /**
214      * Flag indicating that media is currently being loaded.
215      * @see java.awt.MediaTracker#statusAll
216      * @see java.awt.MediaTracker#statusID
217      */

218     public static final int LOADING = 1;
219
220     /**
221      * Flag indicating that the downloading of media was aborted.
222      * @see java.awt.MediaTracker#statusAll
223      * @see java.awt.MediaTracker#statusID
224      */

225     public static final int ABORTED = 2;
226
227     /**
228      * Flag indicating that the downloading of media encountered
229      * an error.
230      * @see java.awt.MediaTracker#statusAll
231      * @see java.awt.MediaTracker#statusID
232      */

233     public static final int ERRORED = 4;
234
235     /**
236      * Flag indicating that the downloading of media was completed
237      * successfully.
238      * @see java.awt.MediaTracker#statusAll
239      * @see java.awt.MediaTracker#statusID
240      */

241     public static final int COMPLETE = 8;
242
243     static final int DONE = (ABORTED | ERRORED | COMPLETE);
244
245     /**
246      * Checks to see if all images being tracked by this media tracker
247      * have finished loading.
248      * <p>
249      * This method does not start loading the images if they are not
250      * already loading.
251      * <p>
252      * If there is an error while loading or scaling an image, then that
253      * image is considered to have finished loading. Use the
254      * <code>isErrorAny</code> or <code>isErrorID</code> methods to
255      * check for errors.
256      * @return <code>true</code> if all images have finished loading,
257      * have been aborted, or have encountered
258      * an error; <code>false</code> otherwise
259      * @see java.awt.MediaTracker#checkAll(boolean)
260      * @see java.awt.MediaTracker#checkID
261      * @see java.awt.MediaTracker#isErrorAny
262      * @see java.awt.MediaTracker#isErrorID
263      */

264     public boolean checkAll() {
265     return checkAll(false, true);
266     }
267
268     /**
269      * Checks to see if all images being tracked by this media tracker
270      * have finished loading.
271      * <p>
272      * If the value of the <code>load</code> flag is <code>true</code>,
273      * then this method starts loading any images that are not yet
274      * being loaded.
275      * <p>
276      * If there is an error while loading or scaling an image, that
277      * image is considered to have finished loading. Use the
278      * <code>isErrorAny</code> and <code>isErrorID</code> methods to
279      * check for errors.
280      * @param load if <code>true</code>, start loading any
281      * images that are not yet being loaded
282      * @return <code>true</code> if all images have finished loading,
283      * have been aborted, or have encountered
284      * an error; <code>false</code> otherwise
285      * @see java.awt.MediaTracker#checkID
286      * @see java.awt.MediaTracker#checkAll()
287      * @see java.awt.MediaTracker#isErrorAny()
288      * @see java.awt.MediaTracker#isErrorID(int)
289      */

290     public boolean checkAll(boolean load) {
291     return checkAll(load, true);
292     }
293
294     private synchronized boolean checkAll(boolean load, boolean verify) {
295     MediaEntry cur = head;
296     boolean done = true;
297     while (cur != null) {
298         if ((cur.getStatus(load, verify) & DONE) == 0) {
299         done = false;
300         }
301         cur = cur.next;
302     }
303     return done;
304     }
305
306     /**
307      * Checks the error status of all of the images.
308      * @return <code>true</code> if any of the images tracked
309      * by this media tracker had an error during
310      * loading; <code>false</code> otherwise
311      * @see java.awt.MediaTracker#isErrorID
312      * @see java.awt.MediaTracker#getErrorsAny
313      */

314     public synchronized boolean isErrorAny() {
315     MediaEntry cur = head;
316     while (cur != null) {
317         if ((cur.getStatus(false, true) & ERRORED) != 0) {
318         return true;
319         }
320         cur = cur.next;
321     }
322     return false;
323     }
324
325     /**
326      * Returns a list of all media that have encountered an error.
327      * @return an array of media objects tracked by this
328      * media tracker that have encountered
329      * an error, or <code>null</code> if
330      * there are none with errors
331      * @see java.awt.MediaTracker#isErrorAny
332      * @see java.awt.MediaTracker#getErrorsID
333      */

334     public synchronized Object JavaDoc[] getErrorsAny() {
335     MediaEntry cur = head;
336     int numerrors = 0;
337     while (cur != null) {
338         if ((cur.getStatus(false, true) & ERRORED) != 0) {
339         numerrors++;
340         }
341         cur = cur.next;
342     }
343     if (numerrors == 0) {
344         return null;
345     }
346     Object JavaDoc errors[] = new Object JavaDoc[numerrors];
347     cur = head;
348     numerrors = 0;
349     while (cur != null) {
350         if ((cur.getStatus(false, false) & ERRORED) != 0) {
351         errors[numerrors++] = cur.getMedia();
352         }
353         cur = cur.next;
354     }
355     return errors;
356     }
357
358     /**
359      * Starts loading all images tracked by this media tracker. This
360      * method waits until all the images being tracked have finished
361      * loading.
362      * <p>
363      * If there is an error while loading or scaling an image, then that
364      * image is considered to have finished loading. Use the
365      * <code>isErrorAny</code> or <code>isErrorID</code> methods to
366      * check for errors.
367      * @see java.awt.MediaTracker#waitForID(int)
368      * @see java.awt.MediaTracker#waitForAll(long)
369      * @see java.awt.MediaTracker#isErrorAny
370      * @see java.awt.MediaTracker#isErrorID
371      * @exception InterruptedException if another thread has
372      * interrupted this thread
373      */

374     public void waitForAll() throws InterruptedException JavaDoc {
375     waitForAll(0);
376     }
377
378     /**
379      * Starts loading all images tracked by this media tracker. This
380      * method waits until all the images being tracked have finished
381      * loading, or until the length of time specified in milliseconds
382      * by the <code>ms</code> argument has passed.
383      * <p>
384      * If there is an error while loading or scaling an image, then
385      * that image is considered to have finished loading. Use the
386      * <code>isErrorAny</code> or <code>isErrorID</code> methods to
387      * check for errors.
388      * @param ms the number of milliseconds to wait
389      * for the loading to complete
390      * @return <code>true</code> if all images were successfully
391      * loaded; <code>false</code> otherwise
392      * @see java.awt.MediaTracker#waitForID(int)
393      * @see java.awt.MediaTracker#waitForAll(long)
394      * @see java.awt.MediaTracker#isErrorAny
395      * @see java.awt.MediaTracker#isErrorID
396      * @exception InterruptedException if another thread has
397      * interrupted this thread.
398      */

399     public synchronized boolean waitForAll(long ms)
400     throws InterruptedException JavaDoc
401     {
402     long end = System.currentTimeMillis() + ms;
403     boolean first = true;
404     while (true) {
405         int status = statusAll(first, first);
406         if ((status & LOADING) == 0) {
407         return (status == COMPLETE);
408         }
409         first = false;
410         long timeout;
411         if (ms == 0) {
412         timeout = 0;
413         } else {
414         timeout = end - System.currentTimeMillis();
415         if (timeout <= 0) {
416             return false;
417         }
418         }
419         wait(timeout);
420     }
421     }
422
423     /**
424      * Calculates and returns the bitwise inclusive <b>OR</b> of the
425      * status of all media that are tracked by this media tracker.
426      * <p>
427      * Possible flags defined by the
428      * <code>MediaTracker</code> class are <code>LOADING</code>,
429      * <code>ABORTED</code>, <code>ERRORED</code>, and
430      * <code>COMPLETE</code>. An image that hasn't started
431      * loading has zero as its status.
432      * <p>
433      * If the value of <code>load</code> is <code>true</code>, then
434      * this method starts loading any images that are not yet being loaded.
435      *
436      * @param load if <code>true</code>, start loading
437      * any images that are not yet being loaded
438      * @return the bitwise inclusive <b>OR</b> of the status of
439      * all of the media being tracked
440      * @see java.awt.MediaTracker#statusID(int, boolean)
441      * @see java.awt.MediaTracker#LOADING
442      * @see java.awt.MediaTracker#ABORTED
443      * @see java.awt.MediaTracker#ERRORED
444      * @see java.awt.MediaTracker#COMPLETE
445      */

446     public int statusAll(boolean load) {
447     return statusAll(load, true);
448     }
449
450     private synchronized int statusAll(boolean load, boolean verify) {
451     MediaEntry cur = head;
452     int status = 0;
453     while (cur != null) {
454         status = status | cur.getStatus(load, verify);
455         cur = cur.next;
456     }
457     return status;
458     }
459
460     /**
461      * Checks to see if all images tracked by this media tracker that
462      * are tagged with the specified identifier have finished loading.
463      * <p>
464      * This method does not start loading the images if they are not
465      * already loading.
466      * <p>
467      * If there is an error while loading or scaling an image, then that
468      * image is considered to have finished loading. Use the
469      * <code>isErrorAny</code> or <code>isErrorID</code> methods to
470      * check for errors.
471      * @param id the identifier of the images to check
472      * @return <code>true</code> if all images have finished loading,
473      * have been aborted, or have encountered
474      * an error; <code>false</code> otherwise
475      * @see java.awt.MediaTracker#checkID(int, boolean)
476      * @see java.awt.MediaTracker#checkAll()
477      * @see java.awt.MediaTracker#isErrorAny()
478      * @see java.awt.MediaTracker#isErrorID(int)
479      */

480     public boolean checkID(int id) {
481     return checkID(id, false, true);
482     }
483
484     /**
485      * Checks to see if all images tracked by this media tracker that
486      * are tagged with the specified identifier have finished loading.
487      * <p>
488      * If the value of the <code>load</code> flag is <code>true</code>,
489      * then this method starts loading any images that are not yet
490      * being loaded.
491      * <p>
492      * If there is an error while loading or scaling an image, then that
493      * image is considered to have finished loading. Use the
494      * <code>isErrorAny</code> or <code>isErrorID</code> methods to
495      * check for errors.
496      * @param id the identifier of the images to check
497      * @param load if <code>true</code>, start loading any
498      * images that are not yet being loaded
499      * @return <code>true</code> if all images have finished loading,
500      * have been aborted, or have encountered
501      * an error; <code>false</code> otherwise
502      * @see java.awt.MediaTracker#checkID(int, boolean)
503      * @see java.awt.MediaTracker#checkAll()
504      * @see java.awt.MediaTracker#isErrorAny()
505      * @see java.awt.MediaTracker#isErrorID(int)
506      */

507     public boolean checkID(int id, boolean load) {
508     return checkID(id, load, true);
509     }
510
511     private synchronized boolean checkID(int id, boolean load, boolean verify)
512     {
513     MediaEntry cur = head;
514     boolean done = true;
515     while (cur != null) {
516         if (cur.getID() == id
517         && (cur.getStatus(load, verify) & DONE) == 0)
518         {
519         done = false;
520         }
521         cur = cur.next;
522     }
523     return done;
524     }
525
526     /**
527      * Checks the error status of all of the images tracked by this
528      * media tracker with the specified identifier.
529      * @param id the identifier of the images to check
530      * @return <code>true</code> if any of the images with the
531      * specified identifier had an error during
532      * loading; <code>false</code> otherwise
533      * @see java.awt.MediaTracker#isErrorAny
534      * @see java.awt.MediaTracker#getErrorsID
535      */

536     public synchronized boolean isErrorID(int id) {
537     MediaEntry cur = head;
538     while (cur != null) {
539         if (cur.getID() == id
540         && (cur.getStatus(false, true) & ERRORED) != 0)
541         {
542         return true;
543         }
544         cur = cur.next;
545     }
546     return false;
547     }
548
549     /**
550      * Returns a list of media with the specified ID that
551      * have encountered an error.
552      * @param id the identifier of the images to check
553      * @return an array of media objects tracked by this media
554      * tracker with the specified identifier
555      * that have encountered an error, or
556      * <code>null</code> if there are none with errors
557      * @see java.awt.MediaTracker#isErrorID
558      * @see java.awt.MediaTracker#isErrorAny
559      * @see java.awt.MediaTracker#getErrorsAny
560      */

561     public synchronized Object JavaDoc[] getErrorsID(int id) {
562     MediaEntry cur = head;
563     int numerrors = 0;
564     while (cur != null) {
565         if (cur.getID() == id
566         && (cur.getStatus(false, true) & ERRORED) != 0)
567         {
568         numerrors++;
569         }
570         cur = cur.next;
571     }
572     if (numerrors == 0) {
573         return null;
574     }
575     Object JavaDoc errors[] = new Object JavaDoc[numerrors];
576     cur = head;
577     numerrors = 0;
578     while (cur != null) {
579         if (cur.getID() == id
580         && (cur.getStatus(false, false) & ERRORED) != 0)
581         {
582         errors[numerrors++] = cur.getMedia();
583         }
584         cur = cur.next;
585     }
586     return errors;
587     }
588
589     /**
590      * Starts loading all images tracked by this media tracker with the
591      * specified identifier. This method waits until all the images with
592      * the specified identifier have finished loading.
593      * <p>
594      * If there is an error while loading or scaling an image, then that
595      * image is considered to have finished loading. Use the
596      * <code>isErrorAny</code> and <code>isErrorID</code> methods to
597      * check for errors.
598      * @param id the identifier of the images to check
599      * @see java.awt.MediaTracker#waitForAll
600      * @see java.awt.MediaTracker#isErrorAny()
601      * @see java.awt.MediaTracker#isErrorID(int)
602      * @exception InterruptedException if another thread has
603      * interrupted this thread.
604      */

605     public void waitForID(int id) throws InterruptedException JavaDoc {
606     waitForID(id, 0);
607     }
608
609     /**
610      * Starts loading all images tracked by this media tracker with the
611      * specified identifier. This method waits until all the images with
612      * the specified identifier have finished loading, or until the
613      * length of time specified in milliseconds by the <code>ms</code>
614      * argument has passed.
615      * <p>
616      * If there is an error while loading or scaling an image, then that
617      * image is considered to have finished loading. Use the
618      * <code>statusID</code>, <code>isErrorID</code>, and
619      * <code>isErrorAny</code> methods to check for errors.
620      * @param id the identifier of the images to check
621      * @param ms the length of time, in milliseconds, to wait
622      * for the loading to complete
623      * @see java.awt.MediaTracker#waitForAll
624      * @see java.awt.MediaTracker#waitForID(int)
625      * @see java.awt.MediaTracker#statusID
626      * @see java.awt.MediaTracker#isErrorAny()
627      * @see java.awt.MediaTracker#isErrorID(int)
628      * @exception InterruptedException if another thread has
629      * interrupted this thread.
630      */

631     public synchronized boolean waitForID(int id, long ms)
632     throws InterruptedException JavaDoc
633     {
634     long end = System.currentTimeMillis() + ms;
635     boolean first = true;
636     while (true) {
637         int status = statusID(id, first, first);
638         if ((status & LOADING) == 0) {
639         return (status == COMPLETE);
640         }
641         first = false;
642         long timeout;
643         if (ms == 0) {
644         timeout = 0;
645         } else {
646         timeout = end - System.currentTimeMillis();
647         if (timeout <= 0) {
648             return false;
649         }
650         }
651         wait(timeout);
652     }
653     }
654
655     /**
656      * Calculates and returns the bitwise inclusive <b>OR</b> of the
657      * status of all media with the specified identifier that are
658      * tracked by this media tracker.
659      * <p>
660      * Possible flags defined by the
661      * <code>MediaTracker</code> class are <code>LOADING</code>,
662      * <code>ABORTED</code>, <code>ERRORED</code>, and
663      * <code>COMPLETE</code>. An image that hasn't started
664      * loading has zero as its status.
665      * <p>
666      * If the value of <code>load</code> is <code>true</code>, then
667      * this method starts loading any images that are not yet being loaded.
668      * @param id the identifier of the images to check
669      * @param load if <code>true</code>, start loading
670      * any images that are not yet being loaded
671      * @return the bitwise inclusive <b>OR</b> of the status of
672      * all of the media with the specified
673      * identifier that are being tracked
674      * @see java.awt.MediaTracker#statusAll(boolean)
675      * @see java.awt.MediaTracker#LOADING
676      * @see java.awt.MediaTracker#ABORTED
677      * @see java.awt.MediaTracker#ERRORED
678      * @see java.awt.MediaTracker#COMPLETE
679      */

680     public int statusID(int id, boolean load) {
681     return statusID(id, load, true);
682     }
683
684     private synchronized int statusID(int id, boolean load, boolean verify) {
685     MediaEntry cur = head;
686     int status = 0;
687     while (cur != null) {
688         if (cur.getID() == id) {
689         status = status | cur.getStatus(load, verify);
690         }
691         cur = cur.next;
692     }
693     return status;
694     }
695
696     /**
697      * Removes the specified image from this media tracker.
698      * All instances of the specified image are removed,
699      * regardless of scale or ID.
700      * @param image the image to be removed
701      * @see java.awt.MediaTracker#removeImage(java.awt.Image, int)
702      * @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int)
703      * @since JDK1.1
704      */

705     public synchronized void removeImage(Image JavaDoc image) {
706     MediaEntry cur = head;
707     MediaEntry prev = null;
708     while (cur != null) {
709         MediaEntry next = cur.next;
710         if (cur.getMedia() == image) {
711         if (prev == null) {
712             head = next;
713         } else {
714             prev.next = next;
715         }
716         cur.cancel();
717         } else {
718         prev = cur;
719         }
720         cur = next;
721     }
722     notifyAll(); // Notify in case remaining images are "done".
723
}
724
725     /**
726      * Removes the specified image from the specified tracking
727      * ID of this media tracker.
728      * All instances of <code>Image</code> being tracked
729      * under the specified ID are removed regardless of scale.
730      * @param image the image to be removed
731      * @param id the tracking ID frrom which to remove the image
732      * @see java.awt.MediaTracker#removeImage(java.awt.Image)
733      * @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int)
734      * @since JDK1.1
735      */

736     public synchronized void removeImage(Image JavaDoc image, int id) {
737     MediaEntry cur = head;
738     MediaEntry prev = null;
739     while (cur != null) {
740         MediaEntry next = cur.next;
741         if (cur.getID() == id && cur.getMedia() == image) {
742         if (prev == null) {
743             head = next;
744         } else {
745             prev.next = next;
746         }
747         cur.cancel();
748         } else {
749         prev = cur;
750         }
751         cur = next;
752     }
753     notifyAll(); // Notify in case remaining images are "done".
754
}
755
756     /**
757      * Removes the specified image with the specified
758      * width, height, and ID from this media tracker.
759      * Only the specified instance (with any duplicates) is removed.
760      * @param image the image to be removed
761      * @param id the tracking ID from which to remove the image
762      * @param width the width to remove (-1 for unscaled)
763      * @param height the height to remove (-1 for unscaled)
764      * @see java.awt.MediaTracker#removeImage(java.awt.Image)
765      * @see java.awt.MediaTracker#removeImage(java.awt.Image, int)
766      * @since JDK1.1
767      */

768     public synchronized void removeImage(Image JavaDoc image, int id,
769                      int width, int height) {
770     MediaEntry cur = head;
771     MediaEntry prev = null;
772     while (cur != null) {
773         MediaEntry next = cur.next;
774         if (cur.getID() == id && cur instanceof ImageMediaEntry
775         && ((ImageMediaEntry) cur).matches(image, width, height))
776         {
777         if (prev == null) {
778             head = next;
779         } else {
780             prev.next = next;
781         }
782         cur.cancel();
783         } else {
784         prev = cur;
785         }
786         cur = next;
787     }
788     notifyAll(); // Notify in case remaining images are "done".
789
}
790
791     synchronized void setDone() {
792     notifyAll();
793     }
794 }
795
796 abstract class MediaEntry {
797     MediaTracker JavaDoc tracker;
798     int ID;
799     MediaEntry next;
800
801     int status;
802     boolean cancelled;
803
804     MediaEntry(MediaTracker JavaDoc mt, int id) {
805     tracker = mt;
806     ID = id;
807     }
808
809     abstract Object JavaDoc getMedia();
810
811     static MediaEntry insert(MediaEntry head, MediaEntry me) {
812     MediaEntry cur = head;
813     MediaEntry prev = null;
814     while (cur != null) {
815         if (cur.ID > me.ID) {
816         break;
817         }
818         prev = cur;
819         cur = cur.next;
820     }
821     me.next = cur;
822     if (prev == null) {
823         head = me;
824     } else {
825         prev.next = me;
826     }
827     return head;
828     }
829
830     int getID() {
831     return ID;
832     }
833
834     abstract void startLoad();
835
836     void cancel() {
837     cancelled = true;
838     }
839
840     static final int LOADING = MediaTracker.LOADING;
841     static final int ABORTED = MediaTracker.ABORTED;
842     static final int ERRORED = MediaTracker.ERRORED;
843     static final int COMPLETE = MediaTracker.COMPLETE;
844
845     static final int LOADSTARTED = (LOADING | ERRORED | COMPLETE);
846     static final int DONE = (ABORTED | ERRORED | COMPLETE);
847
848     synchronized int getStatus(boolean doLoad, boolean doVerify) {
849     if (doLoad && ((status & LOADSTARTED) == 0)) {
850         status = (status & ~ABORTED) | LOADING;
851         startLoad();
852     }
853     return status;
854     }
855
856     void setStatus(int flag) {
857     synchronized (this) {
858         status = flag;
859     }
860     tracker.setDone();
861     }
862 }
863
864 class ImageMediaEntry extends MediaEntry implements ImageObserver JavaDoc,
865 java.io.Serializable JavaDoc {
866     Image JavaDoc image;
867     int width;
868     int height;
869
870     /*
871      * JDK 1.1 serialVersionUID
872      */

873     private static final long serialVersionUID = 4739377000350280650L;
874     
875     ImageMediaEntry(MediaTracker JavaDoc mt, Image JavaDoc img, int c, int w, int h) {
876     super(mt, c);
877     image = img;
878     width = w;
879     height = h;
880     }
881
882     boolean matches(Image JavaDoc img, int w, int h) {
883     return (image == img && width == w && height == h);
884     }
885
886     Object JavaDoc getMedia() {
887     return image;
888     }
889
890     int getStatus(boolean doLoad, boolean doVerify) {
891     if (doVerify) {
892         int flags = tracker.target.checkImage(image, width, height, null);
893         int s = parseflags(flags);
894         if (s == 0) {
895         if ((status & (ERRORED | COMPLETE)) != 0) {
896             setStatus(ABORTED);
897         }
898         } else if (s != status) {
899         setStatus(s);
900         }
901     }
902     return super.getStatus(doLoad, doVerify);
903     }
904
905     void startLoad() {
906     if (tracker.target.prepareImage(image, width, height, this)) {
907         setStatus(COMPLETE);
908     }
909     }
910
911     int parseflags(int infoflags) {
912     if ((infoflags & ERROR) != 0) {
913         return ERRORED;
914     } else if ((infoflags & ABORT) != 0) {
915         return ABORTED;
916     } else if ((infoflags & (ALLBITS | FRAMEBITS)) != 0) {
917         return COMPLETE;
918     }
919     return 0;
920     }
921
922     public boolean imageUpdate(Image JavaDoc img, int infoflags,
923                    int x, int y, int w, int h) {
924     if (cancelled) {
925         return false;
926     }
927     int s = parseflags(infoflags);
928     if (s != 0 && s != status) {
929         setStatus(s);
930     }
931     return ((status & LOADING) != 0);
932     }
933 }
934
Popular Tags