176 lines · 6.2 KB · Java
RawDownload
/* * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.awt.image; import java.lang.ref.WeakReference;import java.awt.Image;import java.awt.image.ImageObserver; public abstract class ImageWatched {    public static Link endlink = new Link();     public Link watcherList;     public ImageWatched() {        watcherList = endlink;    }     /*     * This class defines a node on a linked list of ImageObservers.     * The base class defines the dummy implementation used for the     * last link on all chains and a subsequent subclass then     * defines the standard implementation that manages a weak     * reference to a real ImageObserver.     */    public static class Link {        /*         * Check if iw is the referent of this Link or any         * subsequent Link objects on this chain.         */        public boolean isWatcher(ImageObserver iw) {            return false;  // No "iw" down here.        }         /*         * Remove this Link from the chain if its referent         * is the indicated target or if it has been nulled         * out by the garbage collector.         * Return the new remainder of the chain.         * The argument may be null which will trigger         * the chain to remove only the dead (null) links.         * This method is only ever called inside a         * synchronized block so Link.next modifications         * will be safe.         */        public Link removeWatcher(ImageObserver iw) {            return this;  // Leave me as the end link.        }         /*         * Deliver the indicated image update information         * to the referent of this Link and return a boolean         * indicating whether or not some referent became         * null or has indicated a lack of interest in         * further updates to its imageUpdate() method.         * This method is not called inside a synchronized         * block so Link.next modifications are not safe.         */        public boolean newInfo(Image img, int info,                               int x, int y, int w, int h)        {            return false;  // No disinterested parties down here.        }    }     /*     * Standard Link implementation to manage a Weak Reference     * to an ImageObserver.     */    public static class WeakLink extends Link {        private WeakReference<ImageObserver> myref;        private Link next;         public WeakLink(ImageObserver obs, Link next) {            myref = new WeakReference<ImageObserver>(obs);            this.next = next;        }         public boolean isWatcher(ImageObserver iw) {            return (myref.get() == iw || next.isWatcher(iw));        }         public Link removeWatcher(ImageObserver iw) {            ImageObserver myiw = myref.get();            if (myiw == null) {                // Remove me from the chain, but continue recursion.                return next.removeWatcher(iw);            }            // At this point myiw is not null so we know this test will            // never succeed if this is a pruning pass (iw == null).            if (myiw == iw) {                // Remove me from the chain and end the recursion here.                return next;            }            // I am alive, but not the one to be removed, recurse            // and update my next link and leave me in the chain.            next = next.removeWatcher(iw);            return this;        }         public boolean newInfo(Image img, int info,                               int x, int y, int w, int h)        {            // Note tail recursion because items are added LIFO.            boolean ret = next.newInfo(img, info, x, y, w, h);            ImageObserver myiw = myref.get();            if (myiw == null) {                // My referent is null so we must prune in a second pass.                ret = true;            } else if (myiw.imageUpdate(img, info, x, y, w, h) == false) {                // My referent has lost interest so clear it and ask                // for a pruning pass to remove it later.                myref.clear();                ret = true;            }            return ret;        }    }     public synchronized void addWatcher(ImageObserver iw) {        if (iw != null && !isWatcher(iw)) {            watcherList = new WeakLink(iw, watcherList);        }    }     public synchronized boolean isWatcher(ImageObserver iw) {        return watcherList.isWatcher(iw);    }     public void removeWatcher(ImageObserver iw) {        synchronized (this) {            watcherList = watcherList.removeWatcher(iw);        }        if (watcherList == endlink) {            notifyWatcherListEmpty();        }    }     public boolean isWatcherListEmpty() {        synchronized (this) {            watcherList = watcherList.removeWatcher(null);        }        return (watcherList == endlink);    }     public void newInfo(Image img, int info, int x, int y, int w, int h) {        if (watcherList.newInfo(img, info, x, y, w, h)) {            // Some Link returned true so we now need to prune dead links.            removeWatcher(null);        }    }     protected abstract void notifyWatcherListEmpty();}