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