/**
* Copyright (C) 2009-2014 Cars and Tracks Development Project (CTDP).
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package net.ctdp.rfdynhud.render;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import net.ctdp.rfdynhud.properties.IntProperty;
import net.ctdp.rfdynhud.util.RFDHLog;
import net.ctdp.rfdynhud.util.TextureManager;
import org.jagatoo.util.errorhandling.ParsingException;
import org.jagatoo.util.ini.AbstractIniParser;
/**
* The {@link BorderCache} is used to load borders only once.
*
* @author Marvin Froehlich (CTDP)
*/
public class BorderCache
{
private static final Map<String, Object[]> CACHE = new HashMap<String, Object[]>();
private static String parseTypeFromIni( File iniFile )
{
final String[] type = { null };
try
{
new AbstractIniParser()
{
@Override
protected boolean onSettingParsed( int lineNr, String group, String key, String value, String comment ) throws ParsingException
{
if ( "General".equals( group ) )
{
if ( key.equals( "Type" ) )
{
type[0] = value;
return ( false );
}
}
return ( true );
}
}.parse( iniFile );
}
catch ( Throwable t )
{
RFDHLog.exception( t );
return ( type[0] );
}
return ( type[0] );
}
private static String parseImageFromIni( File iniFile )
{
final String[] image = { null };
try
{
new AbstractIniParser()
{
@Override
protected boolean onSettingParsed( int lineNr, String group, String key, String value, String comment ) throws ParsingException
{
if ( "General".equals( group ) )
{
if ( key.equals( "Image" ) )
{
image[0] = value;
return ( false );
}
}
return ( true );
}
}.parse( iniFile );
}
catch ( Throwable t )
{
RFDHLog.exception( t );
return ( image[0] );
}
return ( image[0] );
}
private static String parseRendererFromIni( File iniFile )
{
final String[] renderer = { null };
try
{
new AbstractIniParser()
{
@Override
protected boolean onSettingParsed( int lineNr, String group, String key, String value, String comment ) throws ParsingException
{
if ( "General".equals( group ) )
{
if ( key.equals( "RendererClass" ) )
{
renderer[0] = value;
return ( false );
}
}
return ( true );
}
}.parse( iniFile );
}
catch ( Throwable t )
{
RFDHLog.exception( t );
return ( renderer[0] );
}
return ( renderer[0] );
}
private static BorderMeasures parseMeasuresFromIni( File iniFile )
{
final BorderMeasures measures = new BorderMeasures();
try
{
new AbstractIniParser()
{
@Override
protected boolean onSettingParsed( int lineNr, String group, String key, String value, String comment ) throws ParsingException
{
if ( "Measures".equals( group ) )
{
if ( key.equals( "LeftWidth" ) )
measures.setLeftWidth( Integer.parseInt( value ) );
else if ( key.equals( "RightWidth" ) )
measures.setRightWidth( Integer.parseInt( value ) );
else if ( key.equals( "TopHeight" ) )
measures.setTopHeight( Integer.parseInt( value ) );
else if ( key.equals( "BottomHeight" ) )
measures.setBottomHeight( Integer.parseInt( value ) );
else if ( key.equals( "InnerLeftWidth" ) )
measures.setInnerLeftWidth( Integer.parseInt( value ) );
else if ( key.equals( "InnerRightWidth" ) )
measures.setInnerRightWidth( Integer.parseInt( value ) );
else if ( key.equals( "InnerTopHeight" ) )
measures.setInnerTopHeight( Integer.parseInt( value ) );
else if ( key.equals( "InnerBottomHeight" ) )
measures.setInnerBottomHeight( Integer.parseInt( value ) );
else if ( key.equals( "OpaqueLeftWidth" ) )
measures.setOpaqueLeftWidth( Integer.parseInt( value ) );
else if ( key.equals( "OpaqueRightWidth" ) )
measures.setOpaqueRightWidth( Integer.parseInt( value ) );
else if ( key.equals( "OpaqueTopHeight" ) )
measures.setOpaqueTopHeight( Integer.parseInt( value ) );
else if ( key.equals( "InnerBottomHeight" ) )
measures.setOpaqueBottomHeight( Integer.parseInt( value ) );
}
return ( true );
}
}.parse( iniFile );
}
catch ( Throwable t )
{
RFDHLog.exception( t );
return ( measures );
}
return ( measures );
}
private static Object[] getFallback( String iniFilename )
{
Object[] bw = { null, null };
CACHE.put( iniFilename, bw );
return ( bw );
}
/**
* Gets or creates a TexturedBorder with the given side widths.
*
* @param bordersBolder
* @param iniFilename the ini filename
* @param paddingTop top padding property
* @param paddingLeft left padding property
* @param paddingRight right padding property
* @param paddingBottom bottom padding property
*
* @return the border
*/
public static BorderWrapper getBorder( File bordersBolder, String iniFilename, IntProperty paddingTop, IntProperty paddingLeft, IntProperty paddingRight, IntProperty paddingBottom )
{
if ( ( iniFilename == null ) || iniFilename.equals( "<NONE>" ) )
{
Object[] border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
Object[] border = CACHE.get( iniFilename );
if ( border != null )
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
if ( File.separatorChar != '/' )
iniFilename = iniFilename.replace( '/', File.separatorChar );
if ( File.separatorChar != '\\' )
iniFilename = iniFilename.replace( '\\', File.separatorChar );
File iniFile = new File( bordersBolder, iniFilename );
if ( !iniFile.exists() || !iniFile.isFile() || !iniFile.getName().toLowerCase().endsWith( ".ini" ) )
{
RFDHLog.error( "[Error] Border ini file invalid \"" + iniFilename + "\"." );
border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
String type = parseTypeFromIni( iniFile );
if ( type == null )
{
RFDHLog.error( "[Error] No \"Type\" setting found in \"" + iniFile.getAbsolutePath() + "\"." );
border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
if ( type.equals( "Image" ) )
{
String textureName = parseImageFromIni( iniFile );
if ( textureName == null )
{
RFDHLog.error( "[Error] No \"Image\" setting found in \"" + iniFile.getAbsolutePath() + "\"." );
border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
File imageFile = new File( bordersBolder, textureName );
TextureImage2D texture = TextureManager.getImage( imageFile.getAbsolutePath(), false ).getTextureImage();
border = new Object[] { new ImageBorderRenderer( textureName, texture ), parseMeasuresFromIni( iniFile ) };
BorderWrapper bw = new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom );
CACHE.put( iniFilename, border );
return ( bw );
}
if ( type.equals( "Renderer" ) )
{
String rendererClass = parseRendererFromIni( iniFile );
if ( rendererClass == null )
{
RFDHLog.error( "[Error] No \"RendererClass\" setting found in \"" + iniFile.getAbsolutePath() + "\"." );
border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
Class<?> clazz = null;
try
{
clazz = Class.forName( rendererClass );
}
catch ( Throwable t )
{
RFDHLog.error( "[Error] Unable to load BorderRenderer class \"" + rendererClass + "\"." );
border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
if ( !BorderRenderer.class.isAssignableFrom( clazz ) )
{
RFDHLog.error( "[Error] \"" + rendererClass + "\" is not a subclass of " + BorderRenderer.class.getName() + "." );
border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
BorderRenderer br = null;
try
{
br = (BorderRenderer)clazz.newInstance();
}
catch ( Throwable t )
{
RFDHLog.error( "[Error] Unable to instantiate " + clazz.getName() + " using default constructor." );
border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
border = new Object[] { br, parseMeasuresFromIni( iniFile ) };
BorderWrapper bw = new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom );
CACHE.put( iniFilename, border );
return ( bw );
}
RFDHLog.error( "[Error] Unknown border type \"" + type + "\" in border ini file \"" + iniFile.getAbsolutePath() + "\"." );
border = getFallback( iniFilename );
return ( new BorderWrapper( (BorderRenderer)border[0], (BorderMeasures)border[1], paddingTop, paddingLeft, paddingRight, paddingBottom ) );
}
}