001/* ========================================================================
002 * JCommon : a free general purpose class library for the Java(tm) platform
003 * ========================================================================
004 *
005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jcommon/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * -------------------------
028 * WaitingImageObserver.java
029 * -------------------------
030 * (C)opyright 2000-2004, by Thomas Morgner and Contributors.
031 *
032 * Original Author:  Thomas Morgner
033 * Contributor(s):   Stefan Prange;
034 *
035 * $Id: WaitingImageObserver.java,v 1.8 2008/09/10 09:24:41 mungady Exp $
036 *
037 * Changes (from 8-Feb-2002)
038 * -------------------------
039 * 15-Apr-2002 : first version used by ImageElement.
040 * 16-May-2002 : Line delimiters adjusted
041 * 04-Jun-2002 : Documentation and added a NullPointerCheck for the constructor.
042 * 14-Jul-2002 : BugFixed: WaitingImageObserver dead-locked (bugfix by Stefan
043 *               Prange)
044 * 18-Mar-2003 : Updated header and made minor Javadoc changes (DG);
045 * 21-Sep-2003 : Moved from JFreeReport.
046 */
047
048package org.jfree.util;
049
050import java.awt.Graphics;
051import java.awt.Image;
052import java.awt.image.BufferedImage;
053import java.awt.image.ImageObserver;
054import java.io.Serializable;
055
056/**
057 * This image observer blocks until the image is completely loaded. AWT
058 * defers the loading of images until they are painted on a graphic.
059 *
060 * While printing reports it is not very nice, not to know whether a image
061 * was completely loaded, so this observer forces the loading of the image
062 * until a final state (either ALLBITS, ABORT or ERROR) is reached.
063 *
064 * @author Thomas Morgner
065 */
066public class WaitingImageObserver implements ImageObserver, Serializable,
067                                             Cloneable
068{
069  /** For serialization. */
070  static final long serialVersionUID = -807204410581383550L;
071
072  /** The lock. */
073  private boolean lock;
074
075  /** The image. */
076  private Image image;
077
078  /** A flag that signals an error. */
079  private boolean error;
080
081  /**
082   * Creates a new <code>ImageObserver<code> for the given <code>Image<code>.
083   * The observer has to be started by an external thread.
084   *
085   * @param image  the image to observe (<code>null</code> not permitted).
086   */
087  public WaitingImageObserver(final Image image) {
088    if (image == null) {
089      throw new NullPointerException();
090    }
091    this.image = image;
092    this.lock = true;
093  }
094
095  /**
096   * Callback function used by AWT to inform that more data is available. The
097   * observer waits until either all data is loaded or AWT signals that the
098   * image cannot be loaded.
099   *
100   * @param     img   the image being observed.
101   * @param     infoflags   the bitwise inclusive OR of the following
102   *               flags:  <code>WIDTH</code>, <code>HEIGHT</code>,
103   *               <code>PROPERTIES</code>, <code>SOMEBITS</code>,
104   *               <code>FRAMEBITS</code>, <code>ALLBITS</code>,
105   *               <code>ERROR</code>, <code>ABORT</code>.
106   * @param     x   the <i>x</i> coordinate.
107   * @param     y   the <i>y</i> coordinate.
108   * @param     width    the width.
109   * @param     height   the height.
110   *
111   * @return    <code>false</code> if the infoflags indicate that the
112   *            image is completely loaded; <code>true</code> otherwise.
113   */
114  public synchronized boolean imageUpdate(
115      final Image img,
116      final int infoflags,
117      final int x,
118      final int y,
119      final int width,
120      final int height) {
121    if ((infoflags & ImageObserver.ALLBITS) == ImageObserver.ALLBITS) {
122        this.lock = false;
123        this.error = false;
124        notifyAll();
125        return false;
126    }
127    else if ((infoflags & ImageObserver.ABORT) == ImageObserver.ABORT
128        || (infoflags & ImageObserver.ERROR) == ImageObserver.ERROR) {
129        this.lock = false;
130        this.error = true;
131        notifyAll();
132        return false;
133    }
134    //notifyAll();
135    return true;
136  }
137
138  /**
139   * The workerthread. Simply draws the image to a BufferedImage's
140   * Graphics-Object and waits for the AWT to load the image.
141   */
142  public synchronized void waitImageLoaded() {
143
144    if (this.lock == false)
145    {
146      return;
147    }
148
149    final BufferedImage img = new BufferedImage(
150        1, 1, BufferedImage.TYPE_INT_RGB
151    );
152    final Graphics g = img.getGraphics();
153
154    while (this.lock) {
155      if (g.drawImage(this.image, 0, 0, img.getWidth(this),
156            img.getHeight(this), this)) {
157        return;
158      }
159
160      try {
161        wait(500);
162      }
163      catch (InterruptedException e) {
164        Log.info(
165          "WaitingImageObserver.waitImageLoaded(): InterruptedException thrown",
166          e
167        );
168      }
169    }
170  }
171
172  /**
173   * Clones this WaitingImageObserver.
174   *
175   * @return a clone.
176   *
177   * @throws CloneNotSupportedException this should never happen.
178   * @deprecated cloning may lock down the observer
179   */
180  public Object clone() throws CloneNotSupportedException {
181    return (WaitingImageObserver) super.clone();
182  }
183
184  /**
185   * Returns <code>true</code> if loading is complete, and <code>false</code>
186   * otherwise.
187   *
188   * @return A boolean.
189   */
190  public boolean isLoadingComplete() {
191    return this.lock == false;
192  }
193
194  /**
195   * Returns true if there is an error condition, and false otherwise.
196   *
197   * @return A boolean.
198   */
199  public boolean isError() {
200    return this.error;
201  }
202}