/*******************************************************************************
* Copyright (c) 2007, 2015 Innoopract Informationssysteme GmbH and others.
* 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
* EclipseSource - ongoing development
******************************************************************************/
package org.eclipse.rap.rwt.internal.theme;
import static org.eclipse.rap.rwt.internal.service.ContextProvider.getApplicationContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.zip.CRC32;
import org.eclipse.rap.rwt.internal.theme.ThemePropertyAdapterRegistry.ThemePropertyAdapter;
import org.eclipse.rap.rwt.internal.util.ParamCheck;
import org.eclipse.rap.rwt.service.ApplicationContext;
import org.eclipse.rap.rwt.service.ResourceLoader;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
public class CssImage implements CssValue, ThemeResource {
private static final String IMAGE_DEST_PATH = "themes/images";
private static final String NONE_INPUT = "none";
public static final CssImage NONE = new CssImage( true, null, null, null, null, true );
private final Size size;
public final boolean none;
public final String path;
public final ResourceLoader loader;
public final String[] gradientColors;
public final float[] gradientPercents;
public final boolean vertical;
/**
* Creates a new image from the given value.
*
* @param path the definition string to create the image from. Either
* <code>none</code> or a path to an image
* @param loader a resource loader which is able to load the image from the
* given path
* @param gradientColors an array with gradient colors
* @param gradientPercents an array with gradient percents
* @param vertical if true sweeps from top to bottom, else
* sweeps from left to right
*/
private CssImage( boolean none,
String path,
ResourceLoader loader,
String[] gradientColors,
float[] gradientPercents,
boolean vertical )
{
this.none = none;
this.path = path;
this.loader = loader;
this.gradientColors = gradientColors;
this.gradientPercents = gradientPercents;
this.vertical = vertical;
if( none ) {
size = new Size( 0, 0 );
} else {
try {
size = readImageSize( path, loader );
if( size == null ) {
throw new IllegalArgumentException( "Failed to read image: " + path );
}
} catch( IOException e ) {
throw new IllegalArgumentException( "Failed to read image: " + path, e );
}
}
}
public static CssImage valueOf( String input, ResourceLoader loader ) {
CssImage result;
if( NONE_INPUT.equals( input ) ) {
result = NONE;
} else {
ParamCheck.notNull( input, "input" );
ParamCheck.notNull( loader, "loader" );
if( input.length() == 0 ) {
throw new IllegalArgumentException( "Empty image path" );
}
result = new CssImage( false, input, loader, null, null, true );
}
return result;
}
public static CssImage createGradient( String[] gradientColors,
float[] gradientPercents,
boolean vertical )
{
CssImage result;
if( gradientColors == null || gradientPercents == null ) {
throw new NullPointerException( "null argument" );
}
result = new CssImage( true, null, null, gradientColors, gradientPercents, vertical );
return result;
}
public boolean isGradient() {
return gradientColors != null && gradientPercents != null;
}
public Size getSize() {
return size;
}
@Override
public String getResourcePath( ApplicationContext applicationContext ) {
String result = null;
if( !none && path != null ) {
ThemePropertyAdapterRegistry registry
= ThemePropertyAdapterRegistry.getInstance( applicationContext );
ThemePropertyAdapter adapter = registry.getPropertyAdapter( CssImage.class );
String cssKey = adapter.getKey( this );
result = IMAGE_DEST_PATH + "/" + cssKey;
}
return result;
}
@Override
public InputStream getResourceAsStream() throws IOException {
InputStream inputStream = null;
if( !none && path != null ) {
inputStream = loader.getResourceAsStream( path );
}
return inputStream;
}
@Override
public String toDefaultString() {
// returns an empty string, because the default resource path is only valid
// for the bundle that specified it
return none ? NONE_INPUT : "";
}
@Override
public boolean equals( Object object ) {
if( object == this ) {
return true;
}
if( object.getClass() == CssImage.class ) {
CssImage other = ( CssImage )object;
return ( path == null ? other.path == null : path.equals( other.path ) )
&& ( loader == null ? other.loader == null : loader.equals( other.loader ) )
&& ( gradientColors == null
? other.gradientColors == null
: Arrays.equals( gradientColors, other.gradientColors ) )
&& ( gradientPercents == null
? other.gradientPercents == null
: Arrays.equals( gradientPercents, other.gradientPercents ) )
&& other.vertical == vertical;
}
return false;
}
@Override
public int hashCode() {
CRC32 result = new CRC32();
if( none ) {
result.update( 1 );
if( gradientColors != null && gradientPercents != null ) {
for( int i = 0; i < gradientColors.length; i++ ) {
result.update( gradientColors[ i ].getBytes() );
}
for( int i = 0; i < gradientPercents.length; i++ ) {
result.update( Float.floatToIntBits( gradientPercents[ i ] ) );
}
if( vertical ) {
result.update( 2 );
}
}
} else {
result.update( 3 );
result.update( path.getBytes() );
}
return ( int )result.getValue();
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append( "CssImage{ " );
if( gradientColors != null && gradientPercents != null ) {
result.append( "gradient: " );
result.append( vertical ? "vertical " : "horizontal " );
for( int i = 0; i < gradientColors.length; i++ ) {
result.append( ", " );
result.append( gradientColors[ i ] );
if( i < gradientPercents.length ) {
result.append( " " );
result.append( gradientPercents[ i ] );
}
}
} else {
result.append( none ? "none" : "path: " + path );
}
result.append( " }" );
return result.toString();
}
public static Image createSwtImage( CssImage image ) throws IOException {
Image result;
if( image.loader == null ) {
String message = "Cannot create image without resource loader";
throw new IllegalArgumentException( message );
}
InputStream inputStream = image.loader.getResourceAsStream( image.path );
try {
result = getApplicationContext().getImageFactory().findImage( image.path, inputStream );
} finally {
inputStream.close();
}
return result;
}
private static Size readImageSize( String path, ResourceLoader loader ) throws IOException {
InputStream inputStream = loader.getResourceAsStream( path );
if( inputStream != null ) {
try {
ImageData data = new ImageData( inputStream );
return new Size( data.width, data.height );
} finally {
inputStream.close();
}
}
return null;
}
}