package org.openslx.util; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.InputStream; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import javax.swing.Icon; import javax.swing.ImageIcon; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; /** * Helper class for loading resources. * This should be error safe loaders with a fall back in case the * requested resource can't be found, or isn't of the expected type. */ public class ResourceLoader { /** * Logger for this class */ private final static Logger LOGGER = Logger.getLogger( ResourceLoader.class ); /** * Load the given resource as an ImageIcon. * This is guaranteed to never throw an Exception and always return * an ImageIcon. If the requested resource could not be loaded, * an icon is generated, containing an error message. If even that * fails, an empty icon is returned. * * @param path Resource path to load * @param description Icon description * @return ImageIcon instance */ public static ImageIcon getIcon( String path, String description ) { URL url = ResourceLoader.class.getResource( path ); if ( url == null ) { LOGGER.error( "Resource not found: " + path ); } else { try { return new ImageIcon( url, description ); } catch ( Exception e ) { LOGGER.error( "Resource not loadable: " + path ); } } // If we reach here loading failed, create image containing error // message try { return errorIcon( "Invalid Resource: " + path ); } catch ( Throwable t ) { return new ImageIcon(); } } public static Icon getIcon( String path, String description, int maxHeight, Component context ) { ImageIcon icon = getIcon( path, description ); return getScaledIcon( icon, maxHeight, context ); } /** * Load the given resource as an ImageIcon. * This is guaranteed to never throw an Exception and always return * an ImageIcon. If the requested resource could not be loaded, * an icon is generated, containing an error message. If even that * fails, an empty icon is returned. * * @param path Resource path to load * @return ImageIcon instance */ public static ImageIcon getIcon( String path ) { return getIcon( path, path ); } /** * Helper that will create an icon with given text. * * @param errorText Text to render to icon * @return the icon */ private static ImageIcon errorIcon( String errorText ) { Font font = new Font( "Tahoma", Font.PLAIN, 20 ); // get dimensions of text FontRenderContext frc = new FontRenderContext( null, true, true ); Rectangle2D bounds = font.getStringBounds( errorText, frc ); int w = (int)bounds.getWidth(); int h = (int)bounds.getHeight(); // create a BufferedImage object BufferedImage image = new BufferedImage( w, h, BufferedImage.TYPE_INT_RGB ); Graphics2D g = image.createGraphics(); // set color and other parameters g.setColor( Color.WHITE ); g.fillRect( 0, 0, w, h ); g.setColor( Color.RED ); g.setFont( font ); g.drawString( errorText, (float)bounds.getX(), (float) -bounds.getY() ); g.dispose(); return new ImageIcon( image, "ERROR" ); } /** * Tries to load the given resource treating it as a text file * * @param path Resource path to load * @return content of the loaded resource as String */ public static String getTextFile( String path ) { String fileContent = null; try ( InputStream stream = ResourceLoader.class.getResourceAsStream( path ) ) { fileContent = IOUtils.toString( stream, StandardCharsets.UTF_8 ); } catch ( Exception e ) { LOGGER.error( "IO error while trying to load resource '" + path + "'. See trace: ", e ); } if ( fileContent != null ) { return fileContent; } else { return "Resource '" + path + "' not found."; } } public static InputStream getStream( String path ) { return ResourceLoader.class.getResourceAsStream( path ); } private static final Map iconCache = new HashMap<>(); public static Icon getScaledIcon( Icon icon, int height, Component context ) { if ( icon == null ) return null; ImageIcon cached = iconCache.get( icon ); if ( cached != null && cached.getIconHeight() == height ) return cached; // Generate? float iHeight = icon.getIconHeight(); float tHeight = height; if ( iHeight <= tHeight ) return icon; // Small enough // Scale down: BufferedImage image = new BufferedImage( icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB ); Graphics2D g = image.createGraphics(); g.setRenderingHint( RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY ); g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); icon.paintIcon( context, g, 0, 0 ); ImageIcon scaledIcon = new ImageIcon( image.getScaledInstance( (int) ( icon.getIconWidth() * ( tHeight / iHeight ) ), (int) ( tHeight ), Image.SCALE_SMOOTH ) ); iconCache.put( icon, scaledIcon ); return scaledIcon; } }