blob: 762ec36c60cf6ba1c43b276a0610d30768079986 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Innoopract Informationssysteme GmbH - initial API and implementation
******************************************************************************/
package org.eclipse.swt.graphics;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.MessageFormat;
import java.util.*;
import javax.imageio.ImageIO;
import org.eclipse.swt.SWT;
import org.eclipse.swt.resources.ResourceManager;
import com.w4t.IResourceManager;
public final class Image {
private static final Map images = new HashMap();
private int width;
private int height;
private Image () {
// prevent instantiation from outside
width = -1;
height = -1;
}
public static synchronized Image find( final String path ) {
IResourceManager manager = ResourceManager.getInstance();
return find( path, manager.getContextLoader() );
}
public static synchronized Image find( final String path,
final ClassLoader imageLoader )
{
if( path == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
Image result;
if( images.containsKey( path ) ) {
result = ( Image )images.get( path );
} else {
result = createImage( path, imageLoader );
}
return result;
}
public static synchronized Image find( final String path,
final InputStream inputStream )
{
if( path == null ) {
SWT.error( SWT.ERROR_NULL_ARGUMENT );
}
Image result;
if( images.containsKey( path ) ) {
result = ( Image )images.get( path );
} else {
result = createImage( path, inputStream );
}
return result;
}
public static synchronized String getPath ( final Image image ) {
String result = null;
Iterator it = images.entrySet().iterator();
boolean next = true;
while( next && it.hasNext() ) {
Map.Entry entry = ( Map.Entry )it.next();
if( entry.getValue().equals( image ) ) {
result = ( String )entry.getKey();
next = false;
}
}
return result;
}
public static synchronized int size(){
return images.size();
}
public static synchronized void clear(){
// TODO: [GR]can we deregister ressources?
// Iterator it = images.keySet().iterator();
// while ( it.hasNext() ) {
// manager.deregister((String)it.next());
// }
images.clear();
}
///////////////////////
// Public Image methods
public Rectangle getBounds() {
Rectangle result = null;
// TODO [rst] Uncomment if constructor provided
// if( isDisposed() ) {
// SWT.error( SWT.ERROR_GRAPHIC_DISPOSED );
// }
if( width != -1 && height != -1 ) {
result = new Rectangle( 0, 0, width, height );
} else {
// TODO [rst] check types
SWT.error( SWT.ERROR_INVALID_IMAGE );
}
return result;
}
//////////////////
// Helping methods
private static Image createImage( final String path,
final ClassLoader imageLoader )
{
Image result;
IResourceManager manager = ResourceManager.getInstance();
ClassLoader loaderBuffer = manager.getContextLoader();
if( imageLoader != null ) {
manager.setContextLoader( imageLoader );
}
try {
InputStream inputStream = manager.getResourceAsStream( path );
result = createImage( path, inputStream );
} finally {
manager.setContextLoader( loaderBuffer );
}
return result;
}
private static Image createImage( final String path,
final InputStream inputStream )
{
if( inputStream == null ) {
String txt = "Image ''{0}'' cannot be found.";
String msg = MessageFormat.format( txt, new Object[] { path } );
SWT.error( SWT.ERROR_INVALID_ARGUMENT,
new IllegalArgumentException( msg ),
msg );
}
Image result = new Image();
////////////////////////////////////////////////////////////////////////////
// TODO: [fappel] Image size calculation and resource registration both
// read the input stream. Because of this I use a workaround
// with a BufferedInputStream. Resetting it after reading the
// image size enables the ResourceManager to reuse it for
// registration. Note that the order is crucial here, since
// the ResourceManager seems to close the stream (shrug).
// It would be nice to find a solution without reading the
// stream twice.
IResourceManager manager = ResourceManager.getInstance();
BufferedInputStream bis = new BufferedInputStream( inputStream );
bis.mark( Integer.MAX_VALUE );
Point size = readImageSize( bis );
if( size != null ) {
result.width = size.x;
result.height = size.y;
}
try {
bis.reset();
} catch( final IOException shouldNotHappen ) {
String txt = "Could not reset input stream while reading image ''{0}''.";
String msg = MessageFormat.format( txt, new Object[] { path } );
throw new RuntimeException( msg, shouldNotHappen );
}
manager.register( path, bis );
////////////////////////////////////////////////////////////////////////////
images.put( path, result );
return result;
}
/**
* @return an array whose first element is the image <em>width</em> and
* second is the <em>height</em>, <code>null</code> if the bounds
* could not be read.
*/
private static Point readImageSize( final InputStream input ) {
Point result = null;
try {
BufferedImage image = ImageIO.read( input );
if( image != null ) {
int width = image.getWidth();
int height = image.getHeight();
result = new Point( width, height );
}
} catch( Exception e ) {
// ImageReader throws IllegalArgumentExceptions for some files
// TODO [rst] log exception
e.printStackTrace();
}
return result;
}
}