/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package tufts.vue;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.File;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.NoSuchElementException;
import java.util.ResourceBundle;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;
import edu.tufts.vue.preferences.implementations.LanguagePreference;
import edu.tufts.vue.preferences.interfaces.VuePreference;
/**
* This class provides a central access method to get a variety of
* resource types. It also can be modified to support caching of
* of resources for performance (todo: yes, implement a result cache).
*
* @version $Revision: 1.63 $ / $Date: 2010-02-03 19:17:41 $ / $Author: mike $
*
*/
public class VueResources
{
private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(VueResources.class);
/** Resource Bundle **/
//protected static final ResourceBundle VueResourceBundle = ResourceBundle.getBundle("tufts.vue.VueResources");
//protected static final ResourceBundle NarraVisionResourceBundle;
protected static final ResourceBundle sResourceBundle;
protected static final ResourceBundle platformBundle;
protected static Map Cache = new HashMap() {
public Object put(Object key, Object value) {
if (value == null) return null;
if (DEBUG.INIT) Log.debug("cached(" + key + ") = " + tufts.Util.tags(value));
return super.put(key, value);
}
};
// Create a LanguagePreference to be used to retrieve the VUE-specific preferred language.
// Can't set the title or description yet because those strings are localized and VueResources
// has to be initialized before localized strings can be fetched. The title and
// description will be set later, and the LanguagePreference will be added to the UI then.
private static LanguagePreference languagePref = LanguagePreference.create(
edu.tufts.vue.preferences.PreferenceConstants.LANGUAGE_CATEGORY,
"language",
null,
null,
null,
false);
static {
final class VueResourceBundle extends ResourceBundle{
// List of bundles in merge bundle
private List<ResourceBundle> bundles;
/**
* Constructs a resource bundle from a list of other resource bundles. If
* there are duplicate keys, the key from the resource bundle with the
* smallest index takes precedence.
* Currently supports merging 2 resource bundles but can be modified for
* any number of resource bundles
* @param baseNameList
* list of bundle base names to search for key/value pairs
*/
public VueResourceBundle(ResourceBundle baseNameList, ResourceBundle childNameList) {
bundles = new ArrayList<ResourceBundle>(2);
bundles.add(baseNameList);
bundles.add(childNameList);
}
@Override
public Enumeration getKeys() {
return new Enumeration(){
Enumeration enumer = null;
int i = 0;
public boolean hasMoreElements(){
boolean b = false;
while (enumer == null || !(b = enumer.hasMoreElements())){
if (i >= bundles.size()){
enumer = null;
return b;
}
enumer = ((ResourceBundle)bundles.get(i++)).getKeys();
}
return b;
}
public Object nextElement(){
if (enumer == null) throw new NoSuchElementException();
return enumer.nextElement();
}
};
}
/*
* (non-Javadoc)
*
* @see java.util.ResourceBundle#handleGetObject(java.lang.String)
*/
@Override
protected Object handleGetObject(String key) {
ResourceBundle rb = null;
String val = null;
for (int i=0;i<bundles.size();i++){
rb = (ResourceBundle) bundles.get(i);
try{
val = rb.getString(key);
}catch (Exception e){}
if (val != null) break;
}
return val;
}
}
if (DEBUG.INIT) tufts.Util.printStackTrace("VueResources; FYI: static init block");
Locale locale = new Locale(languagePref.getLanguage(), languagePref.getCountry());
ResourceBundle langBundle = ResourceBundle.getBundle("tufts.vue.VueResources", locale);
platformBundle = ResourceBundle.getBundle("tufts.vue.VueResources", new Locale("", "", (tufts.Util.isMacPlatform() ? "Mac" : "Win")));
sResourceBundle = new VueResourceBundle(langBundle, platformBundle);
// Locale.setDefault() will set the locale for UI text that's outside VUE's control, eg,
// OK/Cancel on dialogs, text on the filechooser window, etc. Unfortunately, it does NOT affect the left-most menu
// on Mac, and it only changes the text on dialogs and file saving window for French.
Locale.setDefault(locale);
// Since Locale.setDefault(), called above, isn't reliable, the defaults must be set manually.
// Some of these don't work, presumably because they use the wrong key (eg "FileChooser.filesOfTypeLabelText").
javax.swing.UIManager.put("OptionPane.okButtonText", VueResources.getString("OptionPane.okButtonText"));
javax.swing.UIManager.put("OptionPane.cancelButtonText", VueResources.getString("OptionPane.cancelButtonText"));
javax.swing.UIManager.put("OptionPane.yesButtonText", VueResources.getString("OptionPane.yesButtonText"));
javax.swing.UIManager.put("OptionPane.noButtonText", VueResources.getString("OptionPane.noButtonText"));
javax.swing.UIManager.put("FileChooser.openDialogTitleText", VueResources.getString("FileChooser.openDialogTitleText")); // wrong!!
javax.swing.UIManager.put("FileChooser.saveDialogTitleText", VueResources.getString("FileChooser.saveDialogTitleText")); // wrong!!
javax.swing.UIManager.put("FileChooser.fileNameLabelText", VueResources.getString("FileChooser.fileNameLabelText"));
javax.swing.UIManager.put("FileChooser.lookInLabelText", VueResources.getString("FileChooser.lookInLabelText"));
javax.swing.UIManager.put("FileChooser.saveInLabelText", VueResources.getString("FileChooser.saveInLabelText"));
javax.swing.UIManager.put("FileChooser.filesOfTypeLabelText", VueResources.getString("FileChooser.filesOfTypeLabelText")); // wrong!!
javax.swing.UIManager.put("FileChooser.openButtonText", VueResources.getString("FileChooser.openButtonText"));
javax.swing.UIManager.put("FileChooser.saveButtonText", VueResources.getString("FileChooser.saveButtonText"));
javax.swing.UIManager.put("FileChooser.updateButtonText", VueResources.getString("FileChooser.updateButtonText"));
javax.swing.UIManager.put("FileChooser.cancelButtonText", VueResources.getString("FileChooser.cancelButtonText"));
javax.swing.UIManager.put("FileChooser.newFolderButtonText", VueResources.getString("FileChooser.newFolderButtonText"));
javax.swing.UIManager.put("FileChooser.openButtonToolTipText", VueResources.getString("FileChooser.openButtonToolTipText"));
javax.swing.UIManager.put("FileChooser.saveButtonToolTipText", VueResources.getString("FileChooser.saveButtonToolTipText"));
javax.swing.UIManager.put("FileChooser.updateButtonToolTipText", VueResources.getString("FileChooser.updateButtonToolTipText"));
javax.swing.UIManager.put("FileChooser.cancelButtonToolTipText", VueResources.getString("FileChooser.cancelButtonToolTipText"));
javax.swing.UIManager.put("FileChooser.upFolderToolTipText", VueResources.getString("FileChooser.upFolderToolTipText"));
javax.swing.UIManager.put("FileChooser.newFolderToolTipText", VueResources.getString("FileChooser.newFolderToolTipText"));
javax.swing.UIManager.put("FileChooser.listViewButtonToolTipText", VueResources.getString("FileChooser.listViewButtonToolTipText"));
javax.swing.UIManager.put("FileChooser.detailsViewButtonToolTipText", VueResources.getString("FileChooser.detailsViewButtonToolTipText"));
javax.swing.UIManager.put("FileChooser.fileNameHeaderText", VueResources.getString("FileChooser.fileNameHeaderText")); // wrong!!
javax.swing.UIManager.put("FileChooser.fileSizeHeaderText", VueResources.getString("FileChooser.fileSizeHeaderText")); // wrong!!
javax.swing.UIManager.put("FileChooser.fileTypeHeaderText", VueResources.getString("FileChooser.fileTypeHeaderText")); // wrong!!
javax.swing.UIManager.put("FileChooser.fileDateHeaderText", VueResources.getString("FileChooser.fileDateHeaderText")); // wrong!!
javax.swing.UIManager.put("FileChooser.byNameText", VueResources.getString("FileChooser.byNameText")); // wrong!!
javax.swing.UIManager.put("FileChooser.byDateText", VueResources.getString("FileChooser.byDateText")); // wrong!!
javax.swing.UIManager.put("FileChooser.acceptAllFileFilterText", VueResources.getString("FileChooser.acceptAllFileFilterText"));
javax.swing.UIManager.put("InternalFrame.closeButtonToolTip", VueResources.getString("InternalFrame.closeButtonToolTip")); // wrong!!
// This debug code shows the names of all the UI default keys:
/*
javax.swing.UIDefaults defaults = UIManager.getDefaults();
Enumeration keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
System.out.println("!!!!!!!! " + key.toString() + " = " + defaults.get(key));
}
java.util.ResourceBundle bundle = ResourceBundle.getBundle("com.sun.swing.internal.plaf.basic.resources.basic");
java.util.Enumeration<String> keyEn = bundle.getKeys();
System.out.println("Getting all keys, have more elements: " + keyEn.hasMoreElements());
while (keyEn.hasMoreElements()) {
String key = keyEn.nextElement();
// if (key.indexOf("FileChooser") != -1) {
System.out.println(key + ":" + bundle.getString(key));
// }
}
*/
// Now that the resource bundles have been found, the title and description of languagePref can be set
// and it can be added to the UI.
languagePref.setLocalizedStringsAndRegister();
if (DEBUG.INIT) System.out.println("Got bundle: " + sResourceBundle
+ " in locale [" + sResourceBundle.getLocale() + "]");
if (DEBUG.INIT) dumpResource("DEBUG.platform");
}
/*
static {
if (DEBUG.INIT) tufts.Util.printStackTrace("VueResources; FYI: static init block");
String featureSet = null;
String classPath = null;
try {
featureSet = System.getProperty("tufts.vue.features");
classPath = System.getProperty("java.class.path");
if (DEBUG.INIT) System.out.println("CLASSPATH: " + classPath);
} catch (java.security.AccessControlException e) {
System.err.println("Can't access system properties: applet assumed");
}
boolean NarraVision = false;
if (featureSet != null && featureSet.equalsIgnoreCase("NarraVision")) {
NarraVision = true;
} else if (featureSet == null && classPath != null && classPath.toLowerCase().indexOf("narravision") >= 0) {
// If running as a mac app, or explicitly from command line with -Dtufts.vue.featres=NarraVision,
// we know to run as NarraVision. However, if running just from a jar file on the PC,
// we guess from classpath -- if "NarraVision" appears anywhere in it, run
// as MIT NarraVision. (e.g.: "MIT-NarraVision-2005-03-20.jar") will still work.
NarraVision = true;
}
if (NarraVision) {
// This will load VueResources.properties as the parent,
// and then VueResources___NV.properties as the child, who's
// properties will override any duplicate settings the parent.
sResourceBundle = ResourceBundle.getBundle("tufts.vue.VueResources", new Locale("", "", "NV"));
} else {
sResourceBundle = ResourceBundle.getBundle("tufts.vue.VueResources");
}
//NarraVisionResourceBundle = ResourceBundle.getBundle("tufts.vue.VueResources", new Locale("en", "US", "NV"));
NarraVisionResourceBundle = ResourceBundle.getBundle("tufts.vue.VueResources", new Locale("", "", "NV"));
sResourceBundle = NarraVisionResourceBundle;
//sResourceBundle = VueResourceBundle;
//System.out.println("DEFAULT LOCALE: " + Locale.getDefault());
//System.out.println("RESOURCE BUNDLE: " + sResourceBundle + " locale: " + sResourceBundle.getLocale());
// note: as we're in a static block, will only see this if DEBUG.INIT set to true in DEBUG.java
if (DEBUG.INIT) dumpResource("resources.vue");
if (DEBUG.INIT) dumpResource("resources.narravision");
//dumpResource("application.name");
//dumpResource("application.title");
}
*/
public static void main(String[] args) {
}
private static void dumpResource(String name) {
System.out.println(name + ": " + getString(name));
}
/**
* Return the vue resource bundle.
*/
public static ResourceBundle getBundle() {
return sResourceBundle;
}
/**
* This method returns an ImageIcon based on the file
* specified by the properties file
* myIcon=/my/package/myImage.gif
* It will use the resource bulde's class to generate a URL
* to map to local systems.
*
* @param pLookupKey - the key in the properties file
* @returns ImageIcon referenced by the resource bundle's lookupkey balue
**/
public static ImageIcon getImageIcon(Class clazz, String keyOrPath) {
//if (DEBUG.INIT && DEBUG.META) tufts.Util.printStackTrace("getImageIcon " + keyOrPath + " in " + clazz);
String key;
if (clazz == null)
key = keyOrPath;
else
key = clazz.getName() + keyOrPath;
if (Cache.containsKey(key))
return (ImageIcon) Cache.get(key);
ImageIcon icon = null;
if (clazz == null) {
String str = getString(key);
if (str != null)
icon = loadImageIcon(VueResources.class,str);
} else {
icon = loadImageIcon(clazz, keyOrPath);
}
Cache.put(key, icon);
return icon;
}
public static ImageIcon getImageIcon(String key) {
return getImageIcon(null, key);
}
private static boolean isPath(String key) {
return key.indexOf('/') >= 0;
}
public static BufferedImage getBufferedImage(String key)
{
Image i = getImage(key);
int w = i.getWidth(null);
int h = i.getHeight(null);
BufferedImage bi = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
Graphics bg = bi.createGraphics();
bg.drawImage(i,0,0,(ImageObserver)null);
bg.dispose();
return bi;
}
public static Image getImage(String key) {
ImageIcon icon = null;
if (key.charAt(0) == '/')
icon = getImageIcon(VueResources.class, "images" + key);
else
icon = getImageIcon(key);
if (icon != null)
return icon.getImage();
else {
alert("warning: didn't find Image resource with key [" + key + "]");
return null;
}
}
/** @return an image icon loaded from the given resource path */
public static ImageIcon getImageIconResource(String path) {
if (Cache.containsKey(path))
return (ImageIcon) Cache.get(path);
ImageIcon icon = loadImageIcon(path);
Cache.put(path, icon);
return icon;
}
public static Icon getIcon(String key) {
return getImageIcon(key);
}
public static Icon getIcon(Class clazz, String path) {
return getImageIcon(clazz, path);
}
private static ImageIcon loadImageIcon(String file) {
return loadImageIcon(sResourceBundle.getClass(), file);
}
private static ImageIcon loadImageIcon(Class clazz, String file) {
ImageIcon icon = null;
//debug("\tloadImageIcon["+ file + "]");
try {
URL resource = clazz.getResource(file);
//if (DEBUG.INIT) System.out.println("\tURL[" + resource + "]");
if (resource != null) {
icon = new ImageIcon(resource);
if (icon.getImageLoadStatus() != MediaTracker.COMPLETE)
alert("Unable to load image resource " + file +"; URL = '" + resource + "'");
} else {
alert("loadImageIcon; failed to find any resource at: " + file);
}
} catch (Exception e) {
System.err.println(e);
alert("failed to load image icon: " + e);
}
if (DEBUG.INIT && DEBUG.META) System.out.println("\tloadImageIcon[" + file + "] = " + icon);
return icon;
}
public static Dimension getSize(String key) {
if (Cache.containsKey(key))
return (Dimension) Cache.get(key);
String[] data = _getStringArray(key);
if (data == null)
return null;
Dimension d = new Dimension();
if (data.length > 0) {
d.width = parseInt(data[0]);
if (data.length > 1)
d.height = parseInt(data[1]);
}
Cache.put(key, d);
return d;
}
public static Cursor getCursor(String key)
{
String[] data = _getStringArray(key);
if (data == null)
return null;
ImageIcon icon = loadImageIcon(data[0]);
Cursor cursor = null;
if (icon != null) {
Point hot = new Point();
if (data.length > 2) {
hot.x = parseInt(data[1]);
hot.y = parseInt(data[2]);
}
//System.out.println("Creating cursor for " + icon);
//System.out.println("Creating cursor " + key + " " + Arrays.asList(data) + " with hotspot " + hot);
cursor = Toolkit.getDefaultToolkit().createCustomCursor(icon.getImage(), hot, key+":"+icon.toString());
}
return cursor;
}
private static int parseInt(String str) {
return parseInt(str, 0);
}
private static int parseInt(String str, int exceptionValue) {
int i = exceptionValue;
try {
i = Integer.parseInt(str);
} catch (Exception e) {
Log.warn("parseInt: " + e);
if (DEBUG.INIT) e.printStackTrace();
}
return i;
}
private static float parseFloat(String str) {
return parseFloat(str, 0f);
}
private static float parseFloat(String str, float exceptionValue) {
float f = exceptionValue;
try {
f = Float.parseFloat(str);
} catch (Exception e) {
System.err.println(e);
}
return f;
}
public static URL getURL(String pLookupKey)
{
URL url = null;
try {
//url =new File(sResourceBundle.getClass().getResource(getString(pLookupKey)).getFile().replaceAll("%20"," ")).toURL();
//url = sResourceBundle.getClass().getResource(getString(pLookupKey));
url = VueResources.class.getResource(getString(pLookupKey));
if (DEBUG.INIT) alert("URL for key <" + pLookupKey + "> is [" + url + "]");
} catch (Exception e) {
alert(" !!! failed to lead due to "+ e.toString() );
}
return url;
}
public static File getFile(String pLookupKey)
{
File file = null;
try {
file =new File(sResourceBundle.getClass().getResource(getString(pLookupKey)).getFile().replaceAll("%20"," ")) ;
if (!file.exists())
{
System.out.println("getFile is doing class loader thing hopefully YA!!");
//file = new File(ClassLoader.getSystemResource(getString(pLookupKey)).getFile().replaceAll("%20"," "));
URL url = ClassLoader.getSystemResource(getString(pLookupKey));
System.out.println("the url of the " + pLookupKey + " is " + url);
file = new File(url.getFile().replaceAll("%20"," "));
System.out.println("finished with " + file.toString());
if (file == null)
System.err.println("error in getFile method");
else if (!file.exists())
{
System.err.println("getting screwed");
file = null;
}
}
else
{
System.out.println("file exists!!!!!!!!!!");
}
System.out.println("URL found for plookupkey = "+pLookupKey+" : "+file);
} catch (Exception e) {
alert(" !!! failed to lead due to "+ e.toString() );
}
return file;
}
/**
* This method returns the String from a properties file
* for the given lookup key.
* Format: myString=Some Nice Message String
*
* @return String - the result String, null if not found
**/
public final static String getString(String key) {
String result = null;
try {
result = sResourceBundle.getString(key);
if(result==null){
result = platformBundle.getString(key);
}
} catch (MissingResourceException mre) {
// FYI: we get tons of failures that are perfectly okay -- usually due to GUI items
// that are configuring and autmatically check for a bunch of standard sub-keys. Would
// be nice if we could tell the real failures apart from those cases tho...
// (DEBUG.INIT) alert("warning: didn't find String resource with key [" + pLookupKey + // "]");
}
if (DEBUG.INIT) {
if (DEBUG.META /*|| result != null*/)
Log.debug("lookup(" + key + ") = " + (result==null?"null":"\"" + result + "\""));
}
return result;
}
public final static String getString(String key, String defaultString) {
String s = getString(key);
return s == null ? defaultString : s;
}
/** convenience method for localization -- if not found, will use the key as the default for debugging */
public final static String local(String key) {
return getString(key, key);
}
/**
* getStringArray()
* This method returns a String array based on the string in
* the properties file. Commas may not be used in the string.
* There is no escapeingo of commas at this point.
* Format: myStrings=File,Edit,Windows,Help
*
* @param pLookupKey - the key in the properties file
* @return String [] the array -- results are cached for follow-on requests
**/
public static String[] getStringArray(String key) {
if (Cache.containsKey(key))
return (String[]) Cache.get(key);
String[] value = _getStringArray(key);
Cache.put(key, value);
return value;
}
// non-caching string array fetch
private static String[] _getStringArray(String key) {
String[] value = null;
String s = getString(key);
if (s != null)
value = s.split(",\\s*");
return value;
}
/**
* getIntArray
* Thsi method returns an integer array from a properties resource
* The format for the properties file is: myInts=12,13,14,15
* Using a "," (comma) as the separator
* Format: myIntArray=123,456,789
*
* @param String pLookupKey the key of the property
* #return int [] the array of ints
**/
public static int[] getIntArray(String key) {
if (Cache.containsKey(key))
return (int[]) Cache.get(key);
int[] value = _getIntArray(key);
Cache.put(key, value);
return value;
}
private static int[] _getIntArray(String key) {
return _getIntArray(key, 0);
}
// non-caching int array fetch
private static int[] _getIntArray(String key, int minSize) {
int[] value = null;
String[] s = _getStringArray(key);
if (s != null) {
value = new int[Math.max(s.length, minSize)];
for (int i = 0; i < s.length; i++)
value[i] = parseInt(s[i]);
}
return value;
}
private static int[] makeIntArray(String s, int minSize) {
int[] values = null;
if (s != null) {
String[] segs = s.split(",\\s*");
values = new int[Math.max(segs.length, minSize)];
for (int i = 0; i < segs.length; i++) {
//System.out.println("seg"+i+"=[" + segs[i] + "]");
values[i] = parseInt(segs[i]);
}
}
return values;
}
public static float[] getFloatArray(String key) {
if (Cache.containsKey(key))
return (float[]) Cache.get(key);
float[] value = null;
String[] s = _getStringArray(key);
if (s != null) {
value = new float[s.length];
for (int i = 0; i < s.length; i++)
value[i] = parseFloat(s[i]);
}
Cache.put(key, value);
return value;
}
/**
* getInt
* This returns an int based on the int at the lookup key.
* Format: myInt=123
* @param key - the lookup key
* @returns int - the int value in the properties file
**/
static public int getInt( String key)
{
int value = 0;
String s = getString(key);
if (s != null)
value = Integer.parseInt(s);
return value;
}
/**
* getDouble
* This returns a double based on the double at the lookup key.
* Format: myDouble=1.0
* @param key - the lookup key
* @returns double - the double value in the properties file
**/
static public double getDouble(String key)
{
double value = 0;
String s = getString(key);
if (s != null)
value = Double.parseDouble(s);
return value;
}
/**
* getInt
* Returns an int value if one is found for the given key,
* otherwise the default value.
* @param key - the lookup key
* @param pDefault - value to return if none found under key
* @return int - value found or default
*/
static public int getInt(String key, int pDefault)
{
int value = pDefault;
String s = getString(key);
if (s != null) {
Integer i = new Integer(s);
value = i.intValue();
}
return value;
}
/**
* getChar
* Gets a char value for the given key.
* @param key - the lookup key
* @return char - value found or 0 if key not found
*/
static public char getChar(String key)
{
char value = 0;
String s = getString(key);
if (s != null)
value = s.charAt(0);
return value;
}
/** see getFont(key, defaultFont) */
static public Font getFont(String key) {
return getFont(key, null);
}
/**
* This method gets a Font based on the Font string in the
* the properties file. Use format:
* myFont=fontname,plain|bold|italic|bolditalic,size
* or standard java font format:
* myFont=Arial-BOLD-12
*
* @param key the string lookupkey in the properties file
* @param defaultFont -- font to use if none found for given key
* @return Font the Font, or null if missing or malformed
**/
static public Font getFont(String key, Font defaultFont) {
if (Cache.containsKey(key))
return (Font) Cache.get(key);
String spec = getString(key);
Font font = defaultFont;
if (spec != null) {
try {
if (spec.indexOf(',') > 0) {
// Old-style: or own font decoder
String[] parts = getStringArray(key);
String fontName = parts[0];
int style = 0;
if ("bold".equalsIgnoreCase(parts[1])) {
style = Font.BOLD;
} else if ("italic".equalsIgnoreCase(parts[1])) {
style = Font.ITALIC;
} else if ("bolditalic".equalsIgnoreCase(parts[1])) {
style = Font.BOLD + Font. ITALIC;
} else {
style = Font.PLAIN;
}
int size = Integer.parseInt(parts[2]);
font = new Font(fontName, style, size);
} else {
// new style: let Font class decode it (uses dashes instead of commas)
font = Font.decode(spec);
}
} catch (Throwable t) {
alert("Missing or malformed font with key: " + key + " " + t);
}
}
Cache.put(key, font);
return font;
}
/**
* This method gets a color based on the color string in the
* the properties file. Use format: myColor=R,G,B or
* myColor=4F4F4F. E.g.,
*
* myRed=FF0000
* myGreen=00FF00
* myBlue=0000FF
* myRed=255,0,0
* myGreen=0,255,0
* myBlue=0,0,255
*
* Leading zeros may be left off hex values.
*
* @param key the string lookupkey in the properties file
* @return the Color found, or default color if dr != -1
**/
static public Color getColor(String key, Color defaultColor)
{
if (Cache.containsKey(key))
return (Color) Cache.get(key);
Color value = null;
try {
value = parseColor(getString(key));
// String s = getString(key);
// if (s != null) {
// s.trim();
// if (s.indexOf(',') > 0) {
// int[] rgb = makeIntArray(s, 3);
// value = new Color(rgb[0], rgb[1], rgb[2]);
// } else {
// value = makeColor(s);
// }
// }
} catch (java.util.MissingResourceException e) {
; // will try and use default
} catch (Throwable t) {
alert("getColor: " + key + " " + t);
if (DEBUG.INIT) t.printStackTrace();
}
if (value == null) {
if (defaultColor != null)
value = defaultColor;
//if (dr >= 0)
//value = new Color(dr, dg, db);
else
if (DEBUG.INIT) alert("No such resource (color): " + key);
}
Cache.put(key, value);
return value;
}
public static Color parseColor(String txt) {
if (txt == null)
return null;
txt = txt.trim();
if (txt.indexOf(',') > 0)
return parseIntColor(txt);
else
return parseHexColor(txt);
}
static Color parseIntColor(String commaText) {
int[] rgb = makeIntArray(commaText, 3);
if (rgb.length > 3)
return new Color(rgb[0], rgb[1], rgb[2], rgb[3]);
else
return new Color(rgb[0], rgb[1], rgb[2]);
}
static Color parseHexColor(final String _hex) {
String hex = _hex;
if (hex.startsWith("#"))
hex = hex.substring(1);
int separateAlpha = -1;
int i;
if ((i=hex.indexOf('%')) > 0 && hex.length() > (i+1)) {
final String pctTxt = hex.substring(i + 1);
final int pctAlpha = parseInt(pctTxt, -1);
if (pctAlpha != -1) {
float pct = pctAlpha / 100f;
separateAlpha = (int) (pct * 255 + 0.5);
}
hex = hex.substring(0, i);
}
final boolean hasCombinedAlpha = separateAlpha >= 0 || hex.length() > 6;
int bits = Long.valueOf(hex, 16).intValue();
if (separateAlpha > 0) {
// results undefined if any exitings alpha in bits (anything in 0xff000000)
bits &= 0xFFFFFF; // strip any alpha bits that were in the hex value
bits |= (separateAlpha << 24);
}
final Color c = new Color(bits, hasCombinedAlpha);
//Log.debug(String.format("From [%s] (%s) made bits=%X, sepAlpha=%d, netAlpha=%d, %s", _hex, hex, bits, separateAlpha, c.getAlpha(), c));
return c;
}
static public Color getColor(String key) {
return getColor(key, null);
}
/**
* @param dr,dg,db - default R,G,B color values if key not found
*/
static public Color getColor(String key, int dR, int dG, int dB) {
return getColor(key, new Color(dR, dG, dB));
}
// static Color makeColor(String hex) {
// if (hex.startsWith("#"))
// hex = hex.substring(1);
// boolean hasAlpha = hex.length() > 6;
// int bits = Long.valueOf(hex, 16).intValue();
// Color c = new Color(bits, hasAlpha);
// //System.out.println("From " + hex + " made " + c + " alpha=" + c.getAlpha());
// return c;
// }
/**
* getColorArray()
* This method gets a color based on the color string in the
* the properties file. Use formate: myColor=rgbHex
* grayColor=4F4F4F,BBCCDD,FFAAFF
* blue=FF
*
* @param key the string lookupkey in the properties file
* @return Color[] the colors, or null if missing
**/
static public Color[] getColorArray(String key) {
if (Cache.containsKey(key))
return (Color[]) Cache.get(key);
Color [] value = null;
try {
String[] strs = _getStringArray(key);
if( strs != null) {
int len = strs.length;
value = new Color[len];
for (int i=0; i< len; i++) {
value[i] = parseColor(strs[i]);
}
}
} catch (Exception e) {
alert("Missing Color resource: "+key);
value = null;
}
Cache.put(key, value);
return value;
}
/**
* getBool
* Usage: flag=true
*
* @param key the string lookupkey in the properties file
* @return true if found and is set to "true"
**/
static public boolean getBool(String key)
{
boolean value = false;
try {
String str = sResourceBundle.getString( key);
if (str != null)
value = str.equalsIgnoreCase("true");
} catch (Exception e) {
alert("Unknown bool resource: "+key);
}
return value;
}
/***
* getMessageString
* Fetches a message resource string the bundle
* and fills in the parameters
*
* @param key the lookup key
* @param pArgs an object array of parameter strings
*
* @returns the formatted string
**/
static public String getMessageString (String key, Object[] pArgs)
{
String msg = VueResources.getString( key);
msg = MessageFormat.format(msg, pArgs);
return msg;
}
static protected void alert( String pMsg) {
if( DEBUG.Enabled || sDebug || ( get("alerts") != null) )
//System.out.println("VueResources: " + pMsg);
Log.info("alert: " + pMsg);
}
static private String get( String pKey) {
String value = null;
try {
value = getBundle().getString( pKey);
} catch( Exception e) {
}
return value;
}
static public void initComponent( JComponent pObj, String pKey) {
Font font = getFont( pKey+".font");
Color background = getColor( pKey + ".background");
if( font != null)
pObj.setFont(font);
if (background != null && !tufts.vue.gui.GUI.isMacAqua())
pObj.setBackground(background);
if (pObj instanceof JTabbedPane)
pObj.setFocusable(false);
}
/**
* This method returns the formated string in the default
* language
* @param arguments : variable to be placed in the string
* @param pattern : string retrived from the properties file.
* @return
*/
public static String getFormatMessage(Object[] arguments, String pattern){
MessageFormat formatter = new MessageFormat(getString(pattern));
if(arguments!=null){
return formatter.format(arguments);
}else{
return getString(pattern);
}
}
static private boolean sDebug = false;
static protected void debug( String pStr) {
if (sDebug || DEBUG.INIT) System.out.println( pStr);
}
}