2011-04-20 15:37:48 -04:00
|
|
|
package com.fsck.k9.preferences;
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
import java.util.Collections;
|
2011-04-20 15:37:48 -04:00
|
|
|
import java.util.HashMap;
|
2011-12-10 22:57:47 -05:00
|
|
|
import java.util.HashSet;
|
2011-04-20 15:37:48 -04:00
|
|
|
import java.util.Map;
|
2011-12-10 22:57:47 -05:00
|
|
|
import java.util.Set;
|
2012-01-07 22:04:25 -05:00
|
|
|
import java.util.SortedMap;
|
2011-12-10 23:16:22 -05:00
|
|
|
import java.util.TreeMap;
|
2011-10-07 14:29:03 -04:00
|
|
|
import java.util.Map.Entry;
|
|
|
|
|
2011-04-20 15:37:48 -04:00
|
|
|
import android.util.Log;
|
2011-10-07 14:29:03 -04:00
|
|
|
|
|
|
|
import com.fsck.k9.FontSizes;
|
2011-04-20 15:37:48 -04:00
|
|
|
import com.fsck.k9.K9;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO:
|
|
|
|
* - use the default values defined in GlobalSettings and AccountSettings when creating new
|
|
|
|
* accounts
|
|
|
|
* - think of a better way to validate enums than to use the resource arrays (i.e. get rid of
|
|
|
|
* ResourceArrayValidator); maybe even use the settings description for the settings UI
|
|
|
|
* - add unit test that validates the default values are actually valid according to the validator
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class Settings {
|
2011-10-03 18:09:38 -04:00
|
|
|
/**
|
|
|
|
* Version number of global and account settings.
|
|
|
|
*
|
|
|
|
* <p>
|
|
|
|
* This value is used as "version" attribute in the export file. It needs to be incremented
|
|
|
|
* when a global or account setting is added or removed, or when the format of a setting
|
|
|
|
* is changed (e.g. add a value to an enum).
|
|
|
|
* </p>
|
|
|
|
*
|
2011-10-13 23:58:15 -04:00
|
|
|
* @see SettingsExporter
|
2011-10-03 18:09:38 -04:00
|
|
|
*/
|
2012-03-18 23:44:41 -04:00
|
|
|
public static final int VERSION = 7;
|
2011-10-03 18:09:38 -04:00
|
|
|
|
2011-12-11 00:02:31 -05:00
|
|
|
public static Map<String, Object> validate(int version, Map<String,
|
2011-12-10 23:16:22 -05:00
|
|
|
TreeMap<Integer, SettingsDescription>> settings,
|
2011-05-01 22:06:22 -04:00
|
|
|
Map<String, String> importedSettings, boolean useDefaultValues) {
|
2011-04-20 15:37:48 -04:00
|
|
|
|
2011-12-11 00:02:31 -05:00
|
|
|
Map<String, Object> validatedSettings = new HashMap<String, Object>();
|
2011-12-10 23:16:22 -05:00
|
|
|
for (Map.Entry<String, TreeMap<Integer, SettingsDescription>> versionedSetting :
|
|
|
|
settings.entrySet()) {
|
|
|
|
|
2012-01-07 22:04:25 -05:00
|
|
|
// Get the setting description with the highest version lower than or equal to the
|
|
|
|
// supplied content version.
|
|
|
|
TreeMap<Integer, SettingsDescription> versions = versionedSetting.getValue();
|
|
|
|
SortedMap<Integer, SettingsDescription> headMap = versions.headMap(version + 1);
|
2011-12-10 23:16:22 -05:00
|
|
|
|
2012-01-07 22:04:25 -05:00
|
|
|
// Skip this setting if it was introduced after 'version'
|
|
|
|
if (headMap.size() == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Integer settingVersion = headMap.lastKey();
|
|
|
|
SettingsDescription desc = versions.get(settingVersion);
|
|
|
|
|
|
|
|
// Skip this setting if it is no longer used in 'version'
|
|
|
|
if (desc == null) {
|
2011-12-10 23:16:22 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
String key = versionedSetting.getKey();
|
2011-04-20 15:37:48 -04:00
|
|
|
|
|
|
|
boolean useDefaultValue;
|
|
|
|
if (!importedSettings.containsKey(key)) {
|
2011-05-01 22:06:22 -04:00
|
|
|
Log.v(K9.LOG_TAG, "Key \"" + key + "\" wasn't found in the imported file." +
|
|
|
|
((useDefaultValues) ? " Using default value." : ""));
|
|
|
|
useDefaultValue = useDefaultValues;
|
2011-04-20 15:37:48 -04:00
|
|
|
} else {
|
2011-10-07 14:29:03 -04:00
|
|
|
String prettyValue = importedSettings.get(key);
|
|
|
|
try {
|
|
|
|
Object internalValue = desc.fromPrettyString(prettyValue);
|
2011-12-11 00:02:31 -05:00
|
|
|
validatedSettings.put(key, internalValue);
|
2011-04-20 15:37:48 -04:00
|
|
|
useDefaultValue = false;
|
2011-10-07 14:29:03 -04:00
|
|
|
} catch (InvalidSettingValueException e) {
|
|
|
|
Log.v(K9.LOG_TAG, "Key \"" + key + "\" has invalid value \"" + prettyValue +
|
2011-05-01 22:06:22 -04:00
|
|
|
"\" in imported file. " +
|
|
|
|
((useDefaultValues) ? "Using default value." : "Skipping."));
|
|
|
|
useDefaultValue = useDefaultValues;
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (useDefaultValue) {
|
2011-10-07 14:29:03 -04:00
|
|
|
Object defaultValue = desc.getDefaultValue();
|
2011-12-11 00:02:31 -05:00
|
|
|
validatedSettings.put(key, defaultValue);
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return validatedSettings;
|
|
|
|
}
|
|
|
|
|
2011-12-10 22:57:47 -05:00
|
|
|
/**
|
|
|
|
* Upgrade settings using the settings structure and/or special upgrade code.
|
|
|
|
*
|
|
|
|
* @param version
|
|
|
|
* The content version of the settings in {@code validatedSettings}.
|
|
|
|
* @param upgraders
|
|
|
|
* A map of {@link SettingsUpgrader}s for nontrivial settings upgrades.
|
|
|
|
* @param settings
|
|
|
|
* The structure describing the different settings, possibly containing multiple
|
|
|
|
* versions.
|
|
|
|
* @param validatedSettings
|
|
|
|
* The settings as returned by {@link Settings#validate(int, Map, Map, boolean)}.
|
|
|
|
* This map is modified and contains the upgraded settings when this method returns.
|
|
|
|
*
|
|
|
|
* @return A set of setting names that were removed during the upgrade process or {@code null}
|
|
|
|
* if none were removed.
|
|
|
|
*/
|
|
|
|
public static Set<String> upgrade(int version, Map<Integer, SettingsUpgrader> upgraders,
|
|
|
|
Map<String, TreeMap<Integer, SettingsDescription>> settings,
|
2011-12-11 00:02:31 -05:00
|
|
|
Map<String, Object> validatedSettings) {
|
2011-12-10 22:57:47 -05:00
|
|
|
|
2011-12-11 00:02:31 -05:00
|
|
|
Map<String, Object> upgradedSettings = validatedSettings;
|
2011-12-10 22:57:47 -05:00
|
|
|
Set<String> deletedSettings = null;
|
|
|
|
|
|
|
|
for (int toVersion = version + 1; toVersion <= VERSION; toVersion++) {
|
|
|
|
|
|
|
|
// Check if there's an SettingsUpgrader for that version
|
|
|
|
SettingsUpgrader upgrader = upgraders.get(toVersion);
|
|
|
|
if (upgrader != null) {
|
|
|
|
deletedSettings = upgrader.upgrade(upgradedSettings);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deal with settings that don't need special upgrade code
|
|
|
|
for (Entry<String, TreeMap<Integer, SettingsDescription>> versions :
|
|
|
|
settings.entrySet()) {
|
|
|
|
|
|
|
|
String settingName = versions.getKey();
|
|
|
|
TreeMap<Integer, SettingsDescription> versionedSettings = versions.getValue();
|
|
|
|
|
|
|
|
// Handle newly added settings
|
|
|
|
if (versionedSettings.firstKey().intValue() == toVersion) {
|
|
|
|
|
|
|
|
// Check if it was already added to upgradedSettings by the SettingsUpgrader
|
|
|
|
if (!upgradedSettings.containsKey(settingName)) {
|
|
|
|
// Insert default value to upgradedSettings
|
2012-01-07 22:04:25 -05:00
|
|
|
SettingsDescription setting = versionedSettings.get(toVersion);
|
2011-12-10 22:57:47 -05:00
|
|
|
Object defaultValue = setting.getDefaultValue();
|
2011-12-11 00:02:31 -05:00
|
|
|
upgradedSettings.put(settingName, defaultValue);
|
2011-12-10 22:57:47 -05:00
|
|
|
|
|
|
|
if (K9.DEBUG) {
|
|
|
|
String prettyValue = setting.toPrettyString(defaultValue);
|
|
|
|
Log.v(K9.LOG_TAG, "Added new setting \"" + settingName +
|
|
|
|
"\" with default value \"" + prettyValue + "\"");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle removed settings
|
2012-01-07 22:04:25 -05:00
|
|
|
Integer highestVersion = versionedSettings.lastKey();
|
|
|
|
if (highestVersion.intValue() == toVersion &&
|
|
|
|
versionedSettings.get(highestVersion) == null) {
|
2011-12-10 22:57:47 -05:00
|
|
|
upgradedSettings.remove(settingName);
|
|
|
|
if (deletedSettings == null) {
|
|
|
|
deletedSettings = new HashSet<String>();
|
|
|
|
}
|
|
|
|
deletedSettings.add(settingName);
|
|
|
|
|
|
|
|
if (K9.DEBUG) {
|
|
|
|
Log.v(K9.LOG_TAG, "Removed setting \"" + settingName + "\"");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return deletedSettings;
|
|
|
|
}
|
|
|
|
|
2011-12-11 00:02:31 -05:00
|
|
|
/**
|
|
|
|
* Convert settings from the internal representation to the string representation used in the
|
|
|
|
* preference storage.
|
|
|
|
*
|
|
|
|
* @param settings
|
|
|
|
* The map of settings to convert.
|
|
|
|
* @param settingDescriptions
|
|
|
|
* The structure containing the {@link SettingsDescription} objects that will be used
|
|
|
|
* to convert the setting values.
|
|
|
|
*
|
|
|
|
* @return The settings converted to the string representation used in the preference storage.
|
|
|
|
*/
|
|
|
|
public static Map<String, String> convert(Map<String, Object> settings,
|
|
|
|
Map<String, TreeMap<Integer, SettingsDescription>> settingDescriptions) {
|
|
|
|
|
|
|
|
Map<String, String> serializedSettings = new HashMap<String, String>();
|
|
|
|
|
|
|
|
for (Entry<String, Object> setting : settings.entrySet()) {
|
|
|
|
String settingName = setting.getKey();
|
|
|
|
Object internalValue = setting.getValue();
|
|
|
|
|
2012-01-07 22:04:25 -05:00
|
|
|
TreeMap<Integer, SettingsDescription> versionedSetting =
|
|
|
|
settingDescriptions.get(settingName);
|
|
|
|
Integer highestVersion = versionedSetting.lastKey();
|
|
|
|
SettingsDescription settingDesc = versionedSetting.get(highestVersion);
|
2011-12-11 00:02:31 -05:00
|
|
|
|
|
|
|
if (settingDesc != null) {
|
|
|
|
String stringValue = settingDesc.toString(internalValue);
|
|
|
|
|
|
|
|
serializedSettings.put(settingName, stringValue);
|
|
|
|
} else {
|
|
|
|
if (K9.DEBUG) {
|
|
|
|
Log.w(K9.LOG_TAG, "Settings.serialize() called with a setting that should " +
|
|
|
|
"have been removed: " + settingName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return serializedSettings;
|
|
|
|
}
|
|
|
|
|
2011-12-10 23:16:22 -05:00
|
|
|
/**
|
|
|
|
* Creates a {@link TreeMap} linking version numbers to {@link SettingsDescription} instances.
|
|
|
|
*
|
|
|
|
* <p>
|
|
|
|
* This {@code TreeMap} is used to quickly find the {@code SettingsDescription} belonging to a
|
|
|
|
* content version as read by {@link SettingsImporter}. See e.g.
|
|
|
|
* {@link Settings#validate(int, Map, Map, boolean)}.
|
|
|
|
* </p>
|
|
|
|
*
|
|
|
|
* @param versionDescriptions
|
|
|
|
* A list of descriptions for a specific setting mapped to version numbers. Never
|
|
|
|
* {@code null}.
|
|
|
|
*
|
|
|
|
* @return A {@code TreeMap} using the version number as key, the {@code SettingsDescription}
|
|
|
|
* as value.
|
|
|
|
*/
|
|
|
|
public static TreeMap<Integer, SettingsDescription> versions(
|
|
|
|
V... versionDescriptions) {
|
|
|
|
TreeMap<Integer, SettingsDescription> map = new TreeMap<Integer, SettingsDescription>();
|
|
|
|
for (V v : versionDescriptions) {
|
|
|
|
map.put(v.version, v.description);
|
|
|
|
}
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
2011-04-20 15:37:48 -04:00
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* Indicates an invalid setting value.
|
|
|
|
*
|
|
|
|
* @see SettingsDescription#fromString(String)
|
|
|
|
* @see SettingsDescription#fromPrettyString(String)
|
|
|
|
*/
|
|
|
|
public static class InvalidSettingValueException extends Exception {
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Describes a setting.
|
|
|
|
*
|
|
|
|
* <p>
|
|
|
|
* Instances of this class are used to convert the string representations of setting values to
|
|
|
|
* an internal representation (e.g. an integer) and back.
|
|
|
|
* </p><p>
|
|
|
|
* Currently we use two different string representations:
|
|
|
|
* </p>
|
|
|
|
* <ol>
|
|
|
|
* <li>
|
|
|
|
* The one that is used by the internal preference {@link Storage}. It is usually obtained by
|
|
|
|
* calling {@code toString()} on the internal representation of the setting value (see e.g.
|
|
|
|
* {@link K9#save(android.content.SharedPreferences.Editor)}).
|
|
|
|
* </li>
|
|
|
|
* <li>
|
|
|
|
* The "pretty" version that is used by the import/export settings file (e.g. colors are
|
|
|
|
* exported in #rrggbb format instead of a integer string like "-8734021").
|
|
|
|
* </li>
|
|
|
|
* </ol>
|
|
|
|
* <p>
|
|
|
|
* <strong>Note:</strong>
|
|
|
|
* For the future we should aim to get rid of the "internal" string representation. The
|
|
|
|
* "pretty" version makes reading a database dump easier and the performance impact should be
|
|
|
|
* negligible.
|
|
|
|
* </p>
|
|
|
|
*/
|
|
|
|
public static abstract class SettingsDescription {
|
|
|
|
/**
|
|
|
|
* The setting's default value (internal representation).
|
|
|
|
*/
|
|
|
|
protected Object mDefaultValue;
|
2011-04-20 15:37:48 -04:00
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
public SettingsDescription(Object defaultValue) {
|
|
|
|
mDefaultValue = defaultValue;
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* Get the default value.
|
|
|
|
*
|
|
|
|
* @return The internal representation of the default value.
|
|
|
|
*/
|
|
|
|
public Object getDefaultValue() {
|
|
|
|
return mDefaultValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert a setting's value to the string representation.
|
|
|
|
*
|
|
|
|
* @param value
|
|
|
|
* The internal representation of a setting's value.
|
|
|
|
*
|
|
|
|
* @return The string representation of {@code value}.
|
|
|
|
*/
|
|
|
|
public String toString(Object value) {
|
|
|
|
return value.toString();
|
|
|
|
}
|
2011-04-20 15:37:48 -04:00
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* Parse the string representation of a setting's value .
|
|
|
|
*
|
|
|
|
* @param value
|
|
|
|
* The string representation of a setting's value.
|
|
|
|
*
|
|
|
|
* @return The internal representation of the setting's value.
|
|
|
|
*
|
|
|
|
* @throws InvalidSettingValueException
|
|
|
|
* If {@code value} contains an invalid value.
|
|
|
|
*/
|
|
|
|
public abstract Object fromString(String value) throws InvalidSettingValueException;
|
2011-04-20 15:37:48 -04:00
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* Convert a setting value to the "pretty" string representation.
|
|
|
|
*
|
|
|
|
* @param value
|
|
|
|
* The setting's value.
|
|
|
|
*
|
|
|
|
* @return A pretty-printed version of the setting's value.
|
|
|
|
*/
|
|
|
|
public String toPrettyString(Object value) {
|
|
|
|
return toString(value);
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* Convert the pretty-printed version of a setting's value to the internal representation.
|
|
|
|
*
|
|
|
|
* @param value
|
|
|
|
* The pretty-printed version of the setting's value. See
|
|
|
|
* {@link #toPrettyString(Object)}.
|
|
|
|
*
|
|
|
|
* @return The internal representation of the setting's value.
|
|
|
|
*
|
|
|
|
* @throws InvalidSettingValueException
|
|
|
|
* If {@code value} contains an invalid value.
|
|
|
|
*/
|
|
|
|
public Object fromPrettyString(String value) throws InvalidSettingValueException {
|
|
|
|
return fromString(value);
|
|
|
|
}
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
|
2011-12-10 23:16:22 -05:00
|
|
|
/**
|
|
|
|
* Container to hold a {@link SettingsDescription} instance and a version number.
|
|
|
|
*
|
|
|
|
* @see Settings#versions(V...)
|
|
|
|
*/
|
|
|
|
public static class V {
|
|
|
|
public final Integer version;
|
|
|
|
public final SettingsDescription description;
|
|
|
|
|
|
|
|
public V(Integer version, SettingsDescription description) {
|
|
|
|
this.version = version;
|
|
|
|
this.description = description;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-10 22:57:47 -05:00
|
|
|
/**
|
|
|
|
* Used for a nontrivial settings upgrade.
|
|
|
|
*
|
|
|
|
* @see Settings#upgrade(int, Map, Map, Map)
|
|
|
|
*/
|
|
|
|
public interface SettingsUpgrader {
|
|
|
|
/**
|
|
|
|
* Upgrade the provided settings.
|
|
|
|
*
|
|
|
|
* @param settings
|
|
|
|
* The settings to upgrade. This map is modified and contains the upgraded
|
|
|
|
* settings when this method returns.
|
|
|
|
*
|
|
|
|
* @return A set of setting names that were removed during the upgrade process or
|
|
|
|
* {@code null} if none were removed.
|
|
|
|
*/
|
2011-12-11 00:02:31 -05:00
|
|
|
public Set<String> upgrade(Map<String, Object> settings);
|
2011-12-10 22:57:47 -05:00
|
|
|
}
|
|
|
|
|
2011-12-10 23:16:22 -05:00
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* A string setting.
|
|
|
|
*/
|
|
|
|
public static class StringSetting extends SettingsDescription {
|
|
|
|
public StringSetting(String defaultValue) {
|
|
|
|
super(defaultValue);
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
@Override
|
|
|
|
public Object fromString(String value) {
|
|
|
|
return value;
|
|
|
|
}
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* A boolean setting.
|
|
|
|
*/
|
|
|
|
public static class BooleanSetting extends SettingsDescription {
|
|
|
|
public BooleanSetting(boolean defaultValue) {
|
|
|
|
super(defaultValue);
|
|
|
|
}
|
2011-04-20 15:37:48 -04:00
|
|
|
|
|
|
|
@Override
|
2011-10-07 14:29:03 -04:00
|
|
|
public Object fromString(String value) throws InvalidSettingValueException {
|
|
|
|
if (Boolean.TRUE.toString().equals(value)) {
|
|
|
|
return true;
|
|
|
|
} else if (Boolean.FALSE.toString().equals(value)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
throw new InvalidSettingValueException();
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* A color setting.
|
|
|
|
*/
|
|
|
|
public static class ColorSetting extends SettingsDescription {
|
|
|
|
public ColorSetting(int defaultValue) {
|
|
|
|
super(defaultValue);
|
|
|
|
}
|
|
|
|
|
2011-04-20 15:37:48 -04:00
|
|
|
@Override
|
2011-10-07 14:29:03 -04:00
|
|
|
public Object fromString(String value) throws InvalidSettingValueException {
|
2011-04-20 15:37:48 -04:00
|
|
|
try {
|
2011-10-07 14:29:03 -04:00
|
|
|
return Integer.parseInt(value);
|
2011-04-20 15:37:48 -04:00
|
|
|
} catch (NumberFormatException e) {
|
2011-10-07 14:29:03 -04:00
|
|
|
throw new InvalidSettingValueException();
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-10-07 14:29:03 -04:00
|
|
|
public String toPrettyString(Object value) {
|
|
|
|
int color = ((Integer) value) & 0x00FFFFFF;
|
|
|
|
return String.format("#%06x", color);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Object fromPrettyString(String value) throws InvalidSettingValueException {
|
|
|
|
try {
|
|
|
|
if (value.length() == 7) {
|
|
|
|
return Integer.parseInt(value.substring(1), 16) | 0xFF000000;
|
|
|
|
}
|
|
|
|
} catch (NumberFormatException e) { /* do nothing */ }
|
|
|
|
|
|
|
|
throw new InvalidSettingValueException();
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* An {@code Enum} setting.
|
|
|
|
*
|
|
|
|
* <p>
|
|
|
|
* {@link Enum#toString()} is used to obtain the "pretty" string representation.
|
|
|
|
* </p>
|
|
|
|
*/
|
|
|
|
public static class EnumSetting extends SettingsDescription {
|
|
|
|
private Class<? extends Enum<?>> mEnumClass;
|
2011-04-20 15:37:48 -04:00
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
public EnumSetting(Class<? extends Enum<?>> enumClass, Object defaultValue) {
|
|
|
|
super(defaultValue);
|
|
|
|
mEnumClass = enumClass;
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
@SuppressWarnings("unchecked")
|
2011-04-20 15:37:48 -04:00
|
|
|
@Override
|
2011-10-07 14:29:03 -04:00
|
|
|
public Object fromString(String value) throws InvalidSettingValueException {
|
2011-04-20 15:37:48 -04:00
|
|
|
try {
|
2011-10-07 14:29:03 -04:00
|
|
|
return Enum.valueOf((Class<? extends Enum>)mEnumClass, value);
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new InvalidSettingValueException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A setting that has multiple valid values but doesn't use an {@link Enum} internally.
|
|
|
|
*
|
|
|
|
* @param <A>
|
|
|
|
* The type of the internal representation (e.g. {@code Integer}).
|
|
|
|
*/
|
|
|
|
public abstract static class PseudoEnumSetting<A> extends SettingsDescription {
|
|
|
|
public PseudoEnumSetting(Object defaultValue) {
|
|
|
|
super(defaultValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected abstract Map<A, String> getMapping();
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toPrettyString(Object value) {
|
|
|
|
return getMapping().get(value);
|
|
|
|
}
|
2011-04-20 15:37:48 -04:00
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
@Override
|
|
|
|
public Object fromPrettyString(String value) throws InvalidSettingValueException {
|
|
|
|
for (Entry<A, String> entry : getMapping().entrySet()) {
|
|
|
|
if (entry.getValue().equals(value)) {
|
|
|
|
return entry.getKey();
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
throw new InvalidSettingValueException();
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
/**
|
|
|
|
* A font size setting.
|
|
|
|
*/
|
|
|
|
public static class FontSizeSetting extends PseudoEnumSetting<Integer> {
|
|
|
|
private final Map<Integer, String> mMapping;
|
|
|
|
|
|
|
|
public FontSizeSetting(int defaultValue) {
|
|
|
|
super(defaultValue);
|
|
|
|
|
|
|
|
Map<Integer, String> mapping = new HashMap<Integer, String>();
|
2012-01-11 20:18:41 -05:00
|
|
|
mapping.put(FontSizes.FONT_10SP, "tiniest");
|
|
|
|
mapping.put(FontSizes.FONT_12SP, "tiny");
|
2011-10-07 14:29:03 -04:00
|
|
|
mapping.put(FontSizes.SMALL, "smaller");
|
2012-01-11 20:18:41 -05:00
|
|
|
mapping.put(FontSizes.FONT_16SP, "small");
|
2011-10-07 14:29:03 -04:00
|
|
|
mapping.put(FontSizes.MEDIUM, "medium");
|
2012-01-11 20:18:41 -05:00
|
|
|
mapping.put(FontSizes.FONT_20SP, "large");
|
2011-10-07 14:29:03 -04:00
|
|
|
mapping.put(FontSizes.LARGE, "larger");
|
|
|
|
mMapping = Collections.unmodifiableMap(mapping);
|
|
|
|
}
|
|
|
|
|
2011-04-20 15:37:48 -04:00
|
|
|
@Override
|
2011-10-07 14:29:03 -04:00
|
|
|
protected Map<Integer, String> getMapping() {
|
|
|
|
return mMapping;
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
|
2011-10-07 14:29:03 -04:00
|
|
|
@Override
|
|
|
|
public Object fromString(String value) throws InvalidSettingValueException {
|
|
|
|
try {
|
|
|
|
Integer fontSize = Integer.parseInt(value);
|
|
|
|
if (mMapping.containsKey(fontSize)) {
|
|
|
|
return fontSize;
|
|
|
|
}
|
|
|
|
} catch (NumberFormatException e) { /* do nothing */ }
|
|
|
|
|
|
|
|
throw new InvalidSettingValueException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A {@link android.webkit.WebView} font size setting.
|
|
|
|
*/
|
|
|
|
public static class WebFontSizeSetting extends PseudoEnumSetting<Integer> {
|
|
|
|
private final Map<Integer, String> mMapping;
|
|
|
|
|
|
|
|
public WebFontSizeSetting(int defaultValue) {
|
|
|
|
super(defaultValue);
|
|
|
|
|
|
|
|
Map<Integer, String> mapping = new HashMap<Integer, String>();
|
|
|
|
mapping.put(1, "smallest");
|
|
|
|
mapping.put(2, "smaller");
|
|
|
|
mapping.put(3, "normal");
|
|
|
|
mapping.put(4, "larger");
|
|
|
|
mapping.put(5, "largest");
|
|
|
|
mMapping = Collections.unmodifiableMap(mapping);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Map<Integer, String> getMapping() {
|
|
|
|
return mMapping;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Object fromString(String value) throws InvalidSettingValueException {
|
|
|
|
try {
|
|
|
|
Integer fontSize = Integer.parseInt(value);
|
|
|
|
if (mMapping.containsKey(fontSize)) {
|
|
|
|
return fontSize;
|
|
|
|
}
|
|
|
|
} catch (NumberFormatException e) { /* do nothing */ }
|
|
|
|
|
|
|
|
throw new InvalidSettingValueException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An integer settings whose values a limited to a certain range.
|
|
|
|
*/
|
|
|
|
public static class IntegerRangeSetting extends SettingsDescription {
|
|
|
|
private int mStart;
|
|
|
|
private int mEnd;
|
|
|
|
|
|
|
|
public IntegerRangeSetting(int start, int end, int defaultValue) {
|
|
|
|
super(defaultValue);
|
|
|
|
mStart = start;
|
|
|
|
mEnd = end;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Object fromString(String value) throws InvalidSettingValueException {
|
|
|
|
try {
|
|
|
|
int intValue = Integer.parseInt(value);
|
|
|
|
if (mStart <= intValue && intValue <= mEnd) {
|
|
|
|
return intValue;
|
|
|
|
}
|
|
|
|
} catch (NumberFormatException e) { /* do nothing */ }
|
|
|
|
|
|
|
|
throw new InvalidSettingValueException();
|
|
|
|
}
|
2011-04-20 15:37:48 -04:00
|
|
|
}
|
|
|
|
}
|