JAL-4020 class formatting
[jalview.git] / src / jalview / util / ChannelProperties.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.util;
22
23 import java.awt.Image;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.net.URL;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Properties;
36
37 import javax.swing.ImageIcon;
38
39 public class ChannelProperties
40 {
41
42   public static final String CHANNEL_PROPERTIES_FILENAME = "channel.props";
43
44   private static Properties channelProps;
45
46   private static final Properties defaultProps;
47
48   private static Map<String, Image> imageMap = new HashMap<String, Image>();
49
50   private static Map<String, URL> urlMap = new HashMap<String, URL>();
51
52   private static final ArrayList<Image> iconList;
53
54   static
55   {
56     defaultProps = new Properties();
57     // these should be kept up to date, but in real life they should never
58     // actually be used anyway.
59     defaultProps.put("app_name", "Jalview");
60     defaultProps.put("banner", "/default_images/jalview_banner.png");
61     defaultProps.put("logo.16", "/default_images/jalview_logo-16.png");
62     defaultProps.put("logo.32", "/default_images/jalview_logo-32.png");
63     defaultProps.put("logo.38", "/default_images/jalview_logo-38.png");
64     defaultProps.put("logo.48", "/default_images/jalview_logo-48.png");
65     defaultProps.put("logo.64", "/default_images/jalview_logo-64.png");
66     defaultProps.put("logo.128", "/default_images/jalview_logo-128.png");
67     defaultProps.put("logo.256", "/default_images/jalview_logo-256.png");
68     defaultProps.put("logo.512", "/default_images/jalview_logo-512.png");
69     defaultProps.put("rotatable_logo.48",
70             "/default_images/rotatable_jalview_logo-38.png");
71     defaultProps.put("bg_logo.28", "/default_images/barton_group-28.png");
72     defaultProps.put("bg_logo.30", "/default_images/barton_group-30.png");
73     defaultProps.put("bg_logo.32", "/default_images/barton_group-32.png");
74     defaultProps.put("uod_banner.28", "/default_images/UoD_banner-28.png");
75     defaultProps.put("uod_banner.30", "/default_images/UoD_banner-30.png");
76     defaultProps.put("uod_banner.32", "/default_images/UoD_banner-32.png");
77     defaultProps.put("default_appbase",
78             "https://www.jalview.org/getdown/release/1.8");
79     defaultProps.put("preferences.filename", ".jalview_properties");
80
81     // load channel_properties
82     Properties tryChannelProps = new Properties();
83     URL channelPropsURL = ChannelProperties.class
84             .getResource("/" + CHANNEL_PROPERTIES_FILENAME);
85     if (channelPropsURL == null)
86     {
87       // complete failure of channel_properties, set all properties to defaults
88       System.err.println("Failed to find '/" + CHANNEL_PROPERTIES_FILENAME
89               + "' file at '"
90               + (channelPropsURL == null ? "null"
91                       : channelPropsURL.toString())
92               + "'. Using class defaultProps.");
93       tryChannelProps = defaultProps;
94     }
95     else
96     {
97       try
98       {
99         InputStream channelPropsIS = channelPropsURL.openStream();
100         tryChannelProps.load(channelPropsIS);
101         channelPropsIS.close();
102       } catch (IOException e)
103       {
104         System.err.println(e.getMessage());
105         // return false;
106       }
107     }
108     channelProps = tryChannelProps;
109
110     /*
111      * The following slight palava for caching an icon list is so that all sizes of icons
112      * are the same. i.e. if there are /any/ channel_properties icons to use, then _only_
113      * use those channel_properties icons, don't mix in class default icons for missing
114      * sizes.  If there are _no_ (usable) channel icons then we can use the class default icons.
115      */
116     iconList = new ArrayList<Image>();
117     List<String> sizes = Arrays.asList("16", "32", "48", "64", "128", "256",
118             "512");
119     for (String size : sizes)
120     {
121       Image logo = null;
122       // not using defaults or class props first time through
123       logo = ChannelProperties.getImage("logo." + size, null, false);
124       if (logo != null)
125       {
126         iconList.add(logo);
127       }
128     }
129     // now add the class defaults if there were no channel icons defined
130     if (iconList.size() == 0)
131     {
132       for (String size : sizes)
133       {
134         Image logo = null;
135         String path = defaultProps.getProperty("logo." + size);
136         URL imageURL = ChannelProperties.class.getResource(path);
137         ImageIcon imgIcon = imageURL == null ? null
138                 : new ImageIcon(imageURL);
139         logo = imgIcon == null ? null : imgIcon.getImage();
140         if (logo != null)
141         {
142           iconList.add(logo);
143         }
144       }
145     }
146   }
147
148   protected static void loadProps(File dir)
149   {
150     File channelPropsFile = new File(dir, CHANNEL_PROPERTIES_FILENAME);
151     if (channelPropsFile.exists())
152     {
153       try
154       {
155         InputStream is = new FileInputStream(channelPropsFile);
156         channelProps.load(is);
157       } catch (FileNotFoundException e)
158       {
159         System.err.println(e.getMessage());
160       } catch (IOException e)
161       {
162         System.err.println(e.getMessage());
163       }
164     }
165   }
166
167   private static Properties channelProps()
168   {
169     return channelProps;
170   }
171
172   private static Map<String, Image> imageMap()
173   {
174     return imageMap;
175   }
176
177   private static Map<String, URL> urlMap()
178   {
179     return urlMap;
180   }
181
182   /*
183    * getProperty(key) will get property value from channel_properties for key.
184    * If no property for key is found, it will fall back to using the defaultProps defined for this class.
185    */
186   public static String getProperty(String key)
187   {
188     return getProperty(key, null, true);
189   }
190
191   /*
192    * getProperty(key, defaultVal) will get property value from channel_properties for key.
193    * If no property for key is found, it will return defaultVal and NOT fall back to the class defaultProps.
194    */
195   public static String getProperty(String key, String defaultVal)
196   {
197     return getProperty(key, defaultVal, false);
198   }
199
200   /*
201    * internal method.  note that setting useClassDefaultProps=true will ignore the provided defaultVal
202    */
203   private static String getProperty(String key, String defaultVal,
204           boolean useClassDefaultProps)
205   {
206     if (channelProps() != null)
207     {
208       if (channelProps().containsKey(key))
209       {
210         return channelProps().getProperty(key,
211                 useClassDefaultProps ? defaultProps.getProperty(key)
212                         : defaultVal);
213       }
214       else
215       {
216         System.err.println("Failed to get channel property '" + key + "'");
217       }
218     }
219     return null;
220   }
221
222   /*
223    * getImage(key) returns the channel defined image for property key. If that is null (e.g. due to
224    * no defined channel image or the image file being corrupt/unusable/missing) it uses the image
225    * defined in defaultChannelProps
226    */
227   public static Image getImage(String key)
228   {
229     return getImage(key, null, true);
230   }
231
232   /*
233    * getImage(key, defaultImg) will get image associated with value from channel_properties for key.
234    * If no property or associated image for key is found (or is usable), it will return defaultImg
235    * and NOT fall back to the class defaultProps.
236    */
237   public static Image getImage(String key, Image defaultImg)
238   {
239     return getImage(key, defaultImg, false);
240   }
241
242   /*
243    * internal method.  note that setting useClassDefaultImage=true will ignore the provided defaultImg
244    */
245   private static Image getImage(String key, Image defaultImg,
246           boolean useClassDefaultImage)
247   {
248     Image img = null;
249     if (imageMap().containsKey(key))
250     {
251       img = imageMap().get(key);
252     }
253     // Catch a previously untried or failed load
254     if (img == null)
255     {
256       String path = getProperty(key, null, useClassDefaultImage);
257       if (path == null) // no channel property or class default property (if
258                         // requested)
259       {
260         return useClassDefaultImage ? null : defaultImg;
261       }
262
263       URL imageURL = ChannelProperties.class.getResource(path);
264       ImageIcon imgIcon = imageURL == null ? null : new ImageIcon(imageURL);
265       img = imgIcon == null ? null : imgIcon.getImage();
266       if (img == null)
267       {
268         System.err.println(
269                 "Failed to load channel image " + key + "=" + path);
270         if (!useClassDefaultImage)
271         {
272           return defaultImg;
273         }
274       }
275       else
276       {
277         imageMap().put(key, img);
278         urlMap.put(key, imageURL);
279       }
280     }
281     return img;
282   }
283
284   /*
285    * Public method to get the URL object pointing to a cached image.
286    */
287   public static URL getImageURL(String key)
288   {
289     if (getImage(key) != null)
290     {
291       if (urlMap().containsKey(key))
292       {
293         return urlMap().getOrDefault(key, null);
294       }
295       System.err.println(
296               "Do not use getImageURL(key) before using getImage(key...)");
297     }
298     return null;
299   }
300
301   /*
302    * Get a List of Icon images of different sizes.
303    */
304   public static ArrayList<Image> getIconList()
305   {
306     return iconList;
307   }
308 }