JAL-3594 Images for splash screen
[jalview.git] / src / jalview / util / ChannelProperties.java
1 package jalview.util;
2
3 import java.awt.Image;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.net.URL;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Properties;
13
14 import javax.swing.ImageIcon;
15
16 import jalview.bin.Cache;
17
18 public class ChannelProperties
19 {
20
21   private static final String CHANNEL_PROPERTIES_FILENAME = "/channel_properties";
22
23   private static final Properties channelProps;
24
25   private static final Properties defaultProps;
26
27   private static Map<String, Image> imageMap = new HashMap<String, Image>();
28
29   private static Map<String, URL> urlMap = new HashMap<String, URL>();
30
31   private static final ArrayList<Image> iconList;
32
33   static
34   {
35     defaultProps = new Properties();
36     // these should be kept up to date, but in real life they should never
37     // actually be used anyway.
38     defaultProps.put("app_name", "Jalview");
39     defaultProps.put("banner", "/default_images/jalview_banner.png");
40     defaultProps.put("logo.16", "/default_images/jalview_logo-16.png");
41     defaultProps.put("logo.32", "/default_images/jalview_logo-32.png");
42     defaultProps.put("logo.38", "/default_images/jalview_logo-38.png");
43     defaultProps.put("logo.48", "/default_images/jalview_logo-48.png");
44     defaultProps.put("logo.64", "/default_images/jalview_logo-64.png");
45     defaultProps.put("logo.128", "/default_images/jalview_logo-128.png");
46     defaultProps.put("logo.256", "/default_images/jalview_logo-256.png");
47     defaultProps.put("logo.512", "/default_images/jalview_logo-512.png");
48     defaultProps.put("rotatable_logo.48",
49             "/default_images/rotatable_jalview_logo-38.png");
50     defaultProps.put("bg_logo.28", "/default_images/barton_group-28.png");
51     defaultProps.put("bg_logo.30", "/default_images/barton_group-30.png");
52     defaultProps.put("bg_logo.32", "/default_images/barton_group-32.png");
53     defaultProps.put("uod_banner.28", "/default_images/UoD_banner-28.png");
54     defaultProps.put("uod_banner.30", "/default_images/UoD_banner-30.png");
55     defaultProps.put("uod_banner.32", "/default_images/UoD_banner-32.png");
56     defaultProps.put("default_appbase",
57             "https://www.jalview.org/getdown/release/1.8");
58
59     // load channel_properties
60     Properties tryChannelProps = new Properties();
61     URL channelPropsURL = ChannelProperties.class
62             .getResource(CHANNEL_PROPERTIES_FILENAME);
63     if (channelPropsURL == null)
64     {
65       // complete failure of channel_properties, set all properties to defaults
66       System.err.println("Failed to find '" + CHANNEL_PROPERTIES_FILENAME
67               + "' file, using defaults");
68       tryChannelProps = defaultProps;
69     }
70     else
71     {
72       try
73       {
74         InputStream channelPropsIS = channelPropsURL.openStream();
75         tryChannelProps.load(channelPropsIS);
76         channelPropsIS.close();
77       } catch (IOException e)
78       {
79         Cache.log.warn(e.getMessage());
80         // return false;
81       }
82     }
83     channelProps = tryChannelProps;
84
85     /*
86      * The following slight palava for caching an icon list is so that all sizes of icons
87      * are the same. i.e. if there are /any/ channel_properties icons to use, then _only_
88      * use those channel_properties icons, don't mix in class default icons for missing
89      * sizes.  If there are _no_ (usable) channel icons then we can use the class default icons.
90      */
91     iconList = new ArrayList<Image>();
92     List<String> sizes = Arrays.asList("16", "32", "48", "64", "128", "256",
93             "512");
94     for (String size : sizes)
95     {
96       Image logo = null;
97       // not using defaults or class props first time through
98       logo = ChannelProperties.getImage("logo." + size, null, false);
99       if (logo != null)
100       {
101         iconList.add(logo);
102       }
103     }
104     // now add the class defaults if there were no channel icons defined
105     if (iconList.size() == 0)
106     {
107       for (String size : sizes)
108       {
109         Image logo = null;
110         String path = defaultProps.getProperty("logo." + size);
111         URL imageURL = ChannelProperties.class.getResource(path);
112         logo = new ImageIcon(imageURL).getImage();
113         if (logo != null)
114         {
115           iconList.add(logo);
116         }
117       }
118     }
119   }
120
121   private static Properties channelProps()
122   {
123     return channelProps;
124   }
125
126   private static Map<String, Image> imageMap()
127   {
128     return imageMap;
129   }
130
131   private static Map<String, URL> urlMap()
132   {
133     return urlMap;
134   }
135
136   /*
137    * getProperty(key) will get property value from channel_properties for key.
138    * If no property for key is found, it will fall back to using the defaultProps defined for this class.
139    */
140   public static String getProperty(String key)
141   {
142     return getProperty(key, null, true);
143   }
144
145   /*
146    * getProperty(key, defaultVal) will get property value from channel_properties for key.
147    * If no property for key is found, it will return defaultVal and NOT fall back to the class defaultProps.
148    */
149   public static String getProperty(String key, String defaultVal)
150   {
151     return getProperty(key, defaultVal, false);
152   }
153
154   /*
155    * internal method.  note that setting useClassDefaultProps=true will ignore the provided defaultVal
156    */
157   private static String getProperty(String key, String defaultVal,
158           boolean useClassDefaultProps)
159   {
160     if (channelProps() != null)
161     {
162       if (channelProps().containsKey(key))
163       {
164         return channelProps().getProperty(key,
165                 useClassDefaultProps ? defaultProps.getProperty(key)
166                         : defaultVal);
167       }
168       else
169       {
170         System.err.println("Failed to get channel property '" + key + "'");
171       }
172     }
173     return null;
174   }
175
176   /*
177    * getImage(key) returns the channel defined image for property key. If that is null (e.g. due to
178    * no defined channel image or the image file being corrupt/unusable/missing) it uses the image
179    * defined in defaultChannelProps
180    */
181   public static Image getImage(String key)
182   {
183     return getImage(key, null, true);
184   }
185
186   /*
187    * getImage(key, defaultImg) will get image associated with value from channel_properties for key.
188    * If no property or associated image for key is found (or is usable), it will return defaultImg
189    * and NOT fall back to the class defaultProps.
190    */
191   public static Image getImage(String key, Image defaultImg)
192   {
193     return getImage(key, defaultImg, false);
194   }
195
196   /*
197    * internal method.  note that setting useClassDefaultImage=true will ignore the provided defaultImg
198    */
199   private static Image getImage(String key, Image defaultImg,
200           boolean useClassDefaultImage)
201   {
202     Image img = null;
203     if (imageMap().containsKey(key))
204     {
205       img = imageMap().get(key);
206     }
207     // Catch a previously untried or failed load
208     if (img == null)
209     {
210       String path = getProperty(key, null, useClassDefaultImage);
211       if (path == null) // no channel property or class default property (if
212                         // requested)
213       {
214         return useClassDefaultImage ? null : defaultImg;
215       }
216
217       URL imageURL = ChannelProperties.class.getResource(path);
218       img = new ImageIcon(imageURL).getImage();
219       if (img == null)
220       {
221         System.err.println(
222                 "Failed to load channel image " + key + "=" + path);
223         if (!useClassDefaultImage)
224         {
225           return defaultImg;
226         }
227       }
228       else
229       {
230         imageMap().put(key, img);
231         urlMap.put(key, imageURL);
232       }
233     }
234     return img;
235   }
236
237   /*
238    * Public method to get the URL object pointing to a cached image.
239    */
240   public static URL getImageURL(String key)
241   {
242     if (getImage(key) != null)
243     {
244       if (urlMap().containsKey(key))
245       {
246         return urlMap().getOrDefault(key, null);
247       }
248       System.err.println(
249               "Do not use getImageURL(key) before using getImage(key...)");
250     }
251     return null;
252   }
253
254   /*
255    * Get a List of Icon images of different sizes.
256    */
257   public static ArrayList<Image> getIconList()
258   {
259     return iconList;
260   }
261 }