JAL-3746 apply copyright to source
[jalview.git] / src / jalview / util / ChannelProperties.java
index 0b165c7..50d6fc6 100644 (file)
@@ -1,31 +1,55 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.util;
 
 import java.awt.Image;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 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_properties";
+  public static final String CHANNEL_PROPERTIES_FILENAME = "channel.props";
 
-  private Properties channelProps = new Properties();
+  private static Properties channelProps;
 
   private static final Properties defaultProps;
 
-  private Map<String, Image> imageMap = new HashMap<String, Image>();
+  private static Map<String, Image> imageMap = new HashMap<String, Image>();
 
-  private static ChannelProperties instance;
+  private static Map<String, URL> urlMap = new HashMap<String, URL>();
 
-  private boolean initDone = false;
+  private static final ArrayList<Image> iconList;
 
   static
   {
@@ -44,68 +68,115 @@ public class ChannelProperties
     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.62", "/default_images/barton_group-62.png");
-    defaultProps.put("uod_banner", "/default_images/UoD_banner.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");
 
-  private boolean init()
-  {
-    if (initDone)
-    {
-      return initDone;
-    }
     // load channel_properties
-    URL channelPropsURL = getClass()
-            .getResource(CHANNEL_PROPERTIES_FILENAME);
+    Properties tryChannelProps = new Properties();
+    URL channelPropsURL = ChannelProperties.class
+            .getResource("/" + CHANNEL_PROPERTIES_FILENAME);
     if (channelPropsURL == null)
     {
-      // fallback
-      System.err.println("Failed to find '" + CHANNEL_PROPERTIES_FILENAME
-              + "' filem using defaults");
-      channelProps = defaultProps;
-      return false;
+      // 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();
-        channelProps.load(channelPropsIS);
+        tryChannelProps.load(channelPropsIS);
         channelPropsIS.close();
       } catch (IOException e)
       {
-        Cache.log.warn(e.getMessage());
-        return false;
+        System.err.println(e.getMessage());
+        // return false;
       }
     }
-    initDone = true;
-    return initDone;
-  }
+    channelProps = tryChannelProps;
 
-  private ChannelProperties()
-  {
-    init();
+    /*
+     * 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<Image>();
+    List<String> 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);
+        ImageIcon imgIcon = imageURL == null ? null
+                : new ImageIcon(imageURL);
+        logo = imgIcon == null ? null : imgIcon.getImage();
+        if (logo != null)
+        {
+          iconList.add(logo);
+        }
+      }
+    }
   }
 
-  public static ChannelProperties getChannelProperties()
+  protected static void loadProps(File dir)
   {
-    if (instance == null)
+    File channelPropsFile = new File(dir, CHANNEL_PROPERTIES_FILENAME);
+    if (channelPropsFile.exists())
     {
-      instance = new ChannelProperties();
+      try
+      {
+        InputStream is = new FileInputStream(channelPropsFile);
+        channelProps.load(is);
+      } catch (FileNotFoundException e)
+      {
+        System.err.println(e.getMessage());
+      } catch (IOException e)
+      {
+        System.err.println(e.getMessage());
+      }
     }
-    return instance;
   }
 
   private static Properties channelProps()
   {
-    return getChannelProperties().channelProps;
+    return channelProps;
   }
 
   private static Map<String, Image> imageMap()
   {
-    return getChannelProperties().imageMap;
+    return imageMap;
+  }
+
+  private static Map<String, URL> urlMap()
+  {
+    return urlMap;
   }
 
   /*
@@ -126,6 +197,9 @@ public class ChannelProperties
     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)
   {
@@ -145,8 +219,32 @@ public class ChannelProperties
     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))
     {
@@ -155,23 +253,56 @@ public class ChannelProperties
     // Catch a previously untried or failed load
     if (img == null)
     {
-      String path = getProperty(key);
-      if (path == null)
+      String path = getProperty(key, null, useClassDefaultImage);
+      if (path == null) // no channel property or class default property (if
+                        // requested)
       {
-        return null;
+        return useClassDefaultImage ? null : defaultImg;
       }
-      URL imageURL = getChannelProperties().getClass().getResource(path);
-      img = new ImageIcon(imageURL).getImage();
+
+      URL imageURL = ChannelProperties.class.getResource(path);
+      ImageIcon imgIcon = imageURL == null ? null : new ImageIcon(imageURL);
+      img = imgIcon == null ? null : imgIcon.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;
   }
-}
\ No newline at end of file
+
+  /*
+   * 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<Image> getIconList()
+  {
+    return iconList;
+  }
+}