package jalview.util; import java.awt.Image; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.swing.ImageIcon; import jalview.bin.Cache; public class ChannelProperties { private static final String CHANNEL_PROPERTIES_FILENAME = "/channel.props"; private static final Properties channelProps; private static final Properties defaultProps; private static Map imageMap = new HashMap(); private static Map urlMap = new HashMap(); private static final ArrayList iconList; static { defaultProps = new Properties(); // these should be kept up to date, but in real life they should never // actually be used anyway. defaultProps.put("app_name", "Jalview"); defaultProps.put("banner", "/default_images/jalview_banner.png"); defaultProps.put("logo.16", "/default_images/jalview_logo-16.png"); defaultProps.put("logo.32", "/default_images/jalview_logo-32.png"); defaultProps.put("logo.38", "/default_images/jalview_logo-38.png"); defaultProps.put("logo.48", "/default_images/jalview_logo-48.png"); defaultProps.put("logo.64", "/default_images/jalview_logo-64.png"); defaultProps.put("logo.128", "/default_images/jalview_logo-128.png"); defaultProps.put("logo.256", "/default_images/jalview_logo-256.png"); defaultProps.put("logo.512", "/default_images/jalview_logo-512.png"); defaultProps.put("rotatable_logo.48", "/default_images/rotatable_jalview_logo-38.png"); defaultProps.put("bg_logo.28", "/default_images/barton_group-28.png"); defaultProps.put("bg_logo.30", "/default_images/barton_group-30.png"); defaultProps.put("bg_logo.32", "/default_images/barton_group-32.png"); defaultProps.put("uod_banner.28", "/default_images/UoD_banner-28.png"); defaultProps.put("uod_banner.30", "/default_images/UoD_banner-30.png"); defaultProps.put("uod_banner.32", "/default_images/UoD_banner-32.png"); defaultProps.put("default_appbase", "https://www.jalview.org/getdown/release/1.8"); defaultProps.put("preferences.filename", ".jalview_properties"); // load channel_properties Properties tryChannelProps = new Properties(); URL channelPropsURL = ChannelProperties.class .getResource(CHANNEL_PROPERTIES_FILENAME); if (channelPropsURL == null) { // complete failure of channel_properties, set all properties to defaults System.err.println("Failed to find '" + CHANNEL_PROPERTIES_FILENAME + "' file at '" + (channelPropsURL == null ? "null" : channelPropsURL.toString()) + "'. Using class defaultProps."); tryChannelProps = defaultProps; } else { try { InputStream channelPropsIS = channelPropsURL.openStream(); tryChannelProps.load(channelPropsIS); channelPropsIS.close(); } catch (IOException e) { Cache.log.warn(e.getMessage()); // return false; } } channelProps = tryChannelProps; /* * The following slight palava for caching an icon list is so that all sizes of icons * are the same. i.e. if there are /any/ channel_properties icons to use, then _only_ * use those channel_properties icons, don't mix in class default icons for missing * sizes. If there are _no_ (usable) channel icons then we can use the class default icons. */ iconList = new ArrayList(); List sizes = Arrays.asList("16", "32", "48", "64", "128", "256", "512"); for (String size : sizes) { Image logo = null; // not using defaults or class props first time through logo = ChannelProperties.getImage("logo." + size, null, false); if (logo != null) { iconList.add(logo); } } // now add the class defaults if there were no channel icons defined if (iconList.size() == 0) { for (String size : sizes) { Image logo = null; String path = defaultProps.getProperty("logo." + size); URL imageURL = ChannelProperties.class.getResource(path); logo = new ImageIcon(imageURL).getImage(); if (logo != null) { iconList.add(logo); } } } } private static Properties channelProps() { return channelProps; } private static Map imageMap() { return imageMap; } private static Map urlMap() { return urlMap; } /* * getProperty(key) will get property value from channel_properties for key. * If no property for key is found, it will fall back to using the defaultProps defined for this class. */ public static String getProperty(String key) { return getProperty(key, null, true); } /* * getProperty(key, defaultVal) will get property value from channel_properties for key. * If no property for key is found, it will return defaultVal and NOT fall back to the class defaultProps. */ public static String getProperty(String key, String defaultVal) { return getProperty(key, defaultVal, false); } /* * internal method. note that setting useClassDefaultProps=true will ignore the provided defaultVal */ private static String getProperty(String key, String defaultVal, boolean useClassDefaultProps) { if (channelProps() != null) { if (channelProps().containsKey(key)) { return channelProps().getProperty(key, useClassDefaultProps ? defaultProps.getProperty(key) : defaultVal); } else { System.err.println("Failed to get channel property '" + key + "'"); } } return null; } /* * getImage(key) returns the channel defined image for property key. If that is null (e.g. due to * no defined channel image or the image file being corrupt/unusable/missing) it uses the image * defined in defaultChannelProps */ public static Image getImage(String key) { return getImage(key, null, true); } /* * getImage(key, defaultImg) will get image associated with value from channel_properties for key. * If no property or associated image for key is found (or is usable), it will return defaultImg * and NOT fall back to the class defaultProps. */ public static Image getImage(String key, Image defaultImg) { return getImage(key, defaultImg, false); } /* * internal method. note that setting useClassDefaultImage=true will ignore the provided defaultImg */ private static Image getImage(String key, Image defaultImg, boolean useClassDefaultImage) { Image img = null; if (imageMap().containsKey(key)) { img = imageMap().get(key); } // Catch a previously untried or failed load if (img == null) { String path = getProperty(key, null, useClassDefaultImage); if (path == null) // no channel property or class default property (if // requested) { return useClassDefaultImage ? null : defaultImg; } URL imageURL = ChannelProperties.class.getResource(path); img = new ImageIcon(imageURL).getImage(); if (img == null) { System.err.println( "Failed to load channel image " + key + "=" + path); if (!useClassDefaultImage) { return defaultImg; } } else { imageMap().put(key, img); urlMap.put(key, imageURL); } } return img; } /* * Public method to get the URL object pointing to a cached image. */ public static URL getImageURL(String key) { if (getImage(key) != null) { if (urlMap().containsKey(key)) { return urlMap().getOrDefault(key, null); } System.err.println( "Do not use getImageURL(key) before using getImage(key...)"); } return null; } /* * Get a List of Icon images of different sizes. */ public static ArrayList getIconList() { return iconList; } }