/* Copyright (C) 2006 Christian Schneider * * This file is part of Nomad. * * Nomad is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Nomad 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 for more details. * * You should have received a copy of the GNU General Public License * along with Nomad; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Created on Aug 29, 2006 */ package net.sf.nmedit.nmutils.graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.image.ImageObserver; /** * A class that waits until the dimensions of an image become * available and can be obtained by * {@link java.awt.Image#getWidth(java.awt.image.ImageObserver)} * and {@link java.awt.Image#getHeight(java.awt.image.ImageObserver)}. * * @author Christian Schneider */ public final class ImageQuery implements ImageObserver { // the image private final Image image; // true when width is available private boolean availableWidth = false; // true when height is available private boolean availableHeight = false; // true when width and height are available or an error as occured private boolean done = false; // indicates that an error has occured - this does not imply that width and height are not available private boolean failed = false; // indicates whether an time out has occured or not private boolean timedOut = false; /** * Waits until the dimensions of the specified image are available (no time out). * * @see #waitForDimensions(Image, long) */ public static boolean waitForDimensions(Image image) { // no timeout return waitForDimensions(image, 0); } /** * Waits until the dimensions of the specified image are available or an timeout occures. * * @param image the image * @param timeOut <code>0</code> means no time out otherwise it specifies the time out in milliseconds * * @return <code>true</code> when the image dimensions are available * or <code>false</code> when the image is invalid or an timeOut has occured */ public static boolean waitForDimensions(Image image, long timeOut) { return (new ImageQuery(image)).waitForDimensions(timeOut); } private ImageQuery(Image image) { this.image = image; } /** * @param timeOut timeout in milliseconds. <code>0</code> means no time out */ private synchronized boolean waitForDimensions(long timeOut) { // start loading if (!Toolkit.getDefaultToolkit().prepareImage(image, -1, -1, this)) { // the image is not loaded - wait until data becomes available // calculate time out point final long end = System.currentTimeMillis() + timeOut; while (!doAbort()) { if (timeOut!=0) { timeOut = end-System.currentTimeMillis(); if (timeOut<=0) { // timed out timedOut = true; return result(); } } try { wait(timeOut); } catch (InterruptedException e) { } } } else { // the image is already loaded availableWidth = availableHeight = true; } return result(); } /** * @return <code>true</code> when width and height are available */ private boolean result() { return availableWidth && availableHeight; } /** * @return <code>true</code> when an timeout has occured or data is available */ private boolean doAbort() { return done || timedOut; } public synchronized boolean imageUpdate( Image img, int infoflags, int x, int y, int width, int height ) { availableWidth |= (infoflags & ImageObserver.WIDTH) != 0; availableHeight|= (infoflags & ImageObserver.HEIGHT) != 0; failed |= (infoflags & (ImageObserver.ERROR|ImageObserver.ABORT)) != 0; if ((infoflags & ALLBITS) != 0) { availableWidth = availableHeight = true; } if (result() || failed) { // we are done done = true; // wake up notifyAll(); // no more updates required return false; } // still waiting for the info (when not timed out and not done) return !doAbort(); } }