001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Igor V. Stolyarov
019: * @version $Revision$
020: */package java.awt;
021:
022: import java.awt.Component;
023: import java.awt.Image;
024: import java.awt.image.ImageObserver;
025: import java.io.Serializable;
026: import java.util.ArrayList;
027: import java.util.LinkedList;
028: import java.util.ListIterator;
029:
030: public class MediaTracker implements Serializable {
031:
032: private static final long serialVersionUID = -483174189758638095L;
033:
034: public static final int ABORTED = 2;
035:
036: public static final int COMPLETE = 8;
037:
038: public static final int ERRORED = 4;
039:
040: public static final int LOADING = 1;
041:
042: Component owner;
043: LinkedList<TrackingImage> trackingObjects = new LinkedList<TrackingImage>();
044:
045: public MediaTracker(Component comp) {
046: owner = comp;
047: }
048:
049: public void addImage(Image image, int id) {
050: addImage(image, id, -1, -1);
051: }
052:
053: public synchronized void addImage(Image image, int id, int w, int h) {
054: int idx = 0;
055: ListIterator<TrackingImage> li = trackingObjects.listIterator();
056: while (li.hasNext()) {
057: TrackingNode node = li.next();
058: if (id < node.getID()) {
059: idx = li.previousIndex();
060: break;
061: }
062: idx = li.nextIndex();
063: }
064: trackingObjects.add(idx, new TrackingImage(this , image, id, w,
065: h));
066: }
067:
068: public boolean checkAll() {
069: return checkAll(false);
070: }
071:
072: public boolean checkAll(boolean load) {
073: boolean result = true;
074: ListIterator<TrackingImage> li = trackingObjects.listIterator();
075: while (li.hasNext()) {
076: TrackingNode node = li.next();
077: if (load) {
078: node.loadMedia();
079: }
080: if ((node.getState() & TrackingNode.LOADING_DONE) == 0) {
081: result = false;
082: }
083: }
084: return result;
085: }
086:
087: public boolean checkID(int id) {
088: return checkID(id, false);
089: }
090:
091: public boolean checkID(int id, boolean load) {
092: boolean result = true;
093: ListIterator<TrackingImage> li = trackingObjects.listIterator();
094: while (li.hasNext()) {
095: TrackingNode node = li.next();
096: if (node.getID() == id) {
097: if (load) {
098: node.loadMedia();
099: }
100: if ((node.getState() & TrackingNode.LOADING_DONE) == 0) {
101: result = false;
102: }
103: }
104: }
105: return result;
106: }
107:
108: public synchronized Object[] getErrorsAny() {
109: ArrayList<Object> errors = new ArrayList<Object>();
110: ListIterator<TrackingImage> li = trackingObjects.listIterator();
111: while (li.hasNext()) {
112: TrackingNode node = li.next();
113: if ((node.getState() & ERRORED) != 0) {
114: errors.add(node.getMediaObject());
115: }
116: }
117: if (errors.size() == 0) {
118: return null;
119: }
120: return errors.toArray();
121: }
122:
123: public synchronized Object[] getErrorsID(int id) {
124: ArrayList<Object> errors = new ArrayList<Object>();
125: ListIterator<TrackingImage> li = trackingObjects.listIterator();
126: while (li.hasNext()) {
127: TrackingNode node = li.next();
128: if (node.getID() == id) {
129: if ((node.getState() & ERRORED) != 0) {
130: errors.add(node.getMediaObject());
131: }
132: }
133: }
134: if (errors.size() == 0) {
135: return null;
136: }
137: return errors.toArray();
138: }
139:
140: public synchronized boolean isErrorAny() {
141: ListIterator<TrackingImage> li = trackingObjects.listIterator();
142: while (li.hasNext()) {
143: TrackingNode node = li.next();
144: if ((node.getState() & ERRORED) != 0) {
145: return true;
146: }
147: }
148: return false;
149: }
150:
151: public synchronized boolean isErrorID(int id) {
152: ListIterator<TrackingImage> li = trackingObjects.listIterator();
153: while (li.hasNext()) {
154: TrackingNode node = li.next();
155: if (node.getID() == id) {
156: if ((node.getState() & ERRORED) != 0) {
157: return true;
158: }
159: }
160: }
161: return false;
162: }
163:
164: public synchronized void removeImage(Image image) {
165: ListIterator<TrackingImage> li = trackingObjects.listIterator();
166: while (li.hasNext()) {
167: TrackingNode node = li.next();
168: if (node.getMediaObject() == image) {
169: li.remove();
170: }
171: }
172: }
173:
174: public synchronized void removeImage(Image image, int id) {
175: ListIterator<TrackingImage> li = trackingObjects.listIterator();
176: while (li.hasNext()) {
177: TrackingNode node = li.next();
178: if (node.getID() == id && node.getMediaObject() == image) {
179: li.remove();
180: }
181: }
182: }
183:
184: public synchronized void removeImage(Image image, int id,
185: int width, int height) {
186: ListIterator<TrackingImage> li = trackingObjects.listIterator();
187: while (li.hasNext()) {
188: TrackingNode node = li.next();
189: if (node instanceof TrackingImage) {
190: TrackingImage ti = (TrackingImage) node;
191: if (ti.equals(image, id, width, height)) {
192: li.remove();
193: }
194: }
195: }
196: }
197:
198: public int statusAll(boolean load) {
199: int status = 0;
200: ListIterator<TrackingImage> li = trackingObjects.listIterator();
201: while (li.hasNext()) {
202: TrackingNode node = li.next();
203: if (load) {
204: node.loadMedia();
205: }
206: status |= node.getState();
207: }
208: return status;
209: }
210:
211: public int statusID(int id, boolean load) {
212: int status = 0;
213: ListIterator<TrackingImage> li = trackingObjects.listIterator();
214: while (li.hasNext()) {
215: TrackingNode node = li.next();
216: if (id == node.getID()) {
217: if (load) {
218: node.loadMedia();
219: }
220: status |= node.getState();
221: }
222: }
223: return status;
224: }
225:
226: public void waitForAll() throws InterruptedException {
227: waitForAll(0);
228: }
229:
230: public synchronized boolean waitForAll(long ms)
231: throws InterruptedException {
232: boolean needLoad = true;
233: long finishtime = System.currentTimeMillis() + ms;
234: while (true) {
235: int status = statusAll(needLoad);
236: if ((status & LOADING) == 0) {
237: return (status == COMPLETE);
238: }
239: needLoad = false;
240: long timeout;
241: if (ms == 0) {
242: timeout = 0;
243: } else {
244: long curtime = System.currentTimeMillis();
245: if (finishtime <= curtime) {
246: return false;
247: }
248: timeout = finishtime - curtime;
249: }
250: wait(timeout);
251: }
252: }
253:
254: public void waitForID(int id) throws InterruptedException {
255: waitForID(id, 0);
256: }
257:
258: public synchronized boolean waitForID(int id, long ms)
259: throws InterruptedException {
260: boolean needLoad = true;
261: long finishtime = System.currentTimeMillis() + ms;
262: while (true) {
263: int status = statusID(id, needLoad);
264: if ((status & LOADING) == 0) {
265: return (status == COMPLETE);
266: }
267: needLoad = false;
268: long timeout;
269: if (ms == 0) {
270: timeout = 0;
271: } else {
272: long curtime = System.currentTimeMillis();
273: if (finishtime <= curtime) {
274: return false;
275: }
276: timeout = finishtime - curtime;
277: }
278: wait(timeout);
279: }
280: }
281:
282: synchronized void refresh() {
283: notifyAll();
284: }
285:
286: abstract class TrackingNode {
287: final static int LOADING_DONE = ABORTED | ERRORED | COMPLETE;
288: final static int LOADING_STARTED = LOADING | ERRORED | COMPLETE;
289:
290: MediaTracker tracker;
291: int id;
292: int state;
293: TrackingNode next;
294:
295: TrackingNode(MediaTracker tracker, int id) {
296: this .tracker = tracker;
297: this .id = id;
298: }
299:
300: abstract Object getMediaObject();
301:
302: abstract void loadMedia();
303:
304: abstract int getState();
305:
306: int getID() {
307: return id;
308: }
309:
310: void updateState(int state) {
311: synchronized (this ) {
312: this .state = state;
313: }
314: tracker.refresh();
315: }
316:
317: }
318:
319: class TrackingImage extends TrackingNode implements ImageObserver {
320: Image img;
321: int w, h;
322:
323: TrackingImage(MediaTracker tracker, Image image, int id, int w,
324: int h) {
325: super (tracker, id);
326: img = image;
327: this .w = w;
328: this .h = h;
329: }
330:
331: @Override
332: Object getMediaObject() {
333: return img;
334: }
335:
336: @Override
337: void loadMedia() {
338: if ((state & LOADING_STARTED) == 0) {
339: state = (state & ~ABORTED) | LOADING;
340: if (tracker.owner.prepareImage(img, w, h, this )) {
341: updateState(COMPLETE);
342: }
343: }
344: }
345:
346: @Override
347: synchronized int getState() {
348: int infoflags = tracker.owner.checkImage(img, w, h, this );
349: int st = translateFlags(infoflags);
350: if (st != 0 && st != state) {
351: updateState(st);
352: }
353: return state;
354: }
355:
356: int translateFlags(int infoflags) {
357: if ((infoflags & ERROR) != 0) {
358: return ERRORED;
359: } else if ((infoflags & ABORT) != 0) {
360: return ABORTED;
361: } else if ((infoflags & (ALLBITS | FRAMEBITS)) != 0) {
362: return COMPLETE;
363: } else {
364: return 0;
365: }
366: }
367:
368: boolean equals(Image image, int id, int width, int height) {
369: return (image == img && this .id == id && w == width && h == height);
370: }
371:
372: public boolean imageUpdate(Image image, int infoflags, int x,
373: int y, int w, int h) {
374: int st = translateFlags(infoflags);
375: if (st != 0 && st != state) {
376: updateState(st);
377: }
378: return ((state & LOADING) != 0);
379: }
380:
381: }
382:
383: }
|