History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/MediaTracker.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/awt/MediaTracker.java+949−0
@@ -0,0 +1,949 @@
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+}