package ie.dcu.apps.ist; import ie.dcu.swt.SwtUtils; import java.util.*; import java.util.logging.Logger; import java.util.prefs.*; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Display; /** * Manages application preferences * * @author Kevin McGuinness */ public class AppPrefs { public interface Keys { public static final String ENABLE_FEEDBACK = "enable-feedback"; public static final String FOREGROUND_COLOR = "foreground-color"; public static final String BACKGROUND_COLOR = "background-color"; public static final String EXPERIMENT_EMBEDDED = "experiment-embedded"; public static final String CONFIRM_EXIT = "confirm-exit"; public static final String CONFIRM_CLOSE = "confirm-close"; } public interface SupportedTypes { public static final Class INTEGER = Integer.class; public static final Class DOUBLE = Double.class; public static final Class FLOAT = Float.class; public static final Class SHORT = Short.class; public static final Class BYTE = Byte.class; public static final Class LONG = Long.class; public static final Class STRING = String.class; public static final Class BOOLEAN = Boolean.class; public static final Class RGB = RGB.class; } private final Logger log; private final Preferences prefs; private final List listeners; public AppPrefs() { this.log = Logger.getLogger(getClass().getName()); this.prefs = Preferences.userRoot().node(Application.APP_ID); this.listeners = new LinkedList(); addSwtThreadAdaptionListener(); } private void addSwtThreadAdaptionListener() { prefs.addPreferenceChangeListener(new PreferenceChangeListener() { public void preferenceChange(PreferenceChangeEvent evt) { firePreferenceChangedSynced(evt); } }); } private void firePreferenceChangedSynced(final PreferenceChangeEvent evt) { // Delegate to event SWT event dispatching thread Display.getDefault().syncExec(new Runnable() { public void run() { firePreferenceChanged(evt); } }); } private void firePreferenceChanged(PreferenceChangeEvent evt) { for (PreferenceChangeListener listener : listeners) { listener.preferenceChange(evt); } } public void sync() { try { prefs.sync(); } catch (BackingStoreException e) { log.warning("Error syncing preferences: " + e.getMessage()); } } public void flush() { try { prefs.flush(); } catch (BackingStoreException e) { log.warning("Error writing preferences: " + e.getMessage()); } } public void clear() { try { prefs.clear(); } catch (BackingStoreException e) { log.warning("Error clearing preferences: " + e.getMessage()); } } public String[] keys() { try { return prefs.keys(); } catch (BackingStoreException e) { log.warning("Error retrieving preference keys: " + e.getMessage()); } return new String[0]; } public void remove(String key) { prefs.remove(key); } public T get(Class clazz, String key, T def) { String value = (def != null) ? get(key, def.toString()) : get(key, null); return decode(clazz, value, def); } public void put(Class clazz, String key, T value) { prefs.put(key, encode(clazz, value)); } public void put(String key, String value) { prefs.put(key, value); } public String get(String key, String def) { return prefs.get(key, def); } public void addPreferenceChangeListener(PreferenceChangeListener pcl) { listeners.add(pcl); } public void removePreferenceChangeListener(PreferenceChangeListener pcl) { listeners.remove(pcl); } public String encode(Class clazz, T value) { if (clazz.equals(RGB.class)) { return encodeRGB((RGB) value); } else if (value != null) { return String.valueOf(value); } else { return null; } } public T decode(Class clazz, String str, T def) { if (str == null) { return def; } else if (isNumeric(clazz)) { return clazz.cast(decodeNumeric(clazz, str, def)); } else if (isString(clazz)) { return clazz.cast(str); } else if (isBoolean(clazz)) { return clazz.cast(decodeBoolean(str, (Boolean) def)); } else if (clazz.equals(RGB.class)) { return clazz.cast(decodeRGB(str, (RGB) def)); } else { log.warning("Unable to decode class: " + clazz.getName()); } return def; } private boolean isString(Class clazz) { return clazz.equals(String.class); } private boolean isBoolean(Class clazz) { return clazz.equals(Boolean.class); } private boolean isNumeric(Class clazz) { return clazz.equals(Integer.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Short.class) || clazz.equals(Byte.class) || clazz.equals(Long.class); } private RGB decodeRGB(String str, RGB def) { if (str.startsWith("#")) { try { int hex = Integer.parseInt(str.substring(1), 16); return SwtUtils.int2rgb(hex); } catch (NumberFormatException e) { log.warning("Not a valid color: " + str); } } return def; } private String encodeRGB(RGB rgb) { return String.format("#%06x", SwtUtils.rgb2int(rgb)); } private boolean decodeBoolean(String str, boolean def) { return str.equalsIgnoreCase("true") || (str.equalsIgnoreCase("false") ? false : def); } private T decodeNumeric(Class clazz, String s, T def) { try { if (clazz.equals(Integer.class)) { return clazz.cast(Integer.parseInt(s)); } else if (clazz.equals(Double.class)) { return clazz.cast(Double.parseDouble(s)); } else if (clazz.equals(Float.class)) { return clazz.cast(Float.parseFloat(s)); } else if (clazz.equals(Short.class)) { return clazz.cast(Short.parseShort(s)); } else if (clazz.equals(Byte.class)) { return clazz.cast(Byte.parseByte(s)); } else if (clazz.equals(Long.class)) { return clazz.cast(Long.parseLong(s)); } } catch (NumberFormatException ex) { log.warning("Invalid numeric value in preferences: " + s); } return def; } }