diff --git a/app/build.gradle b/app/build.gradle index b0e229b5..71a98c7f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,6 @@ dependencies { compile 'org.solovyev.android:android-common-other:1.1.18@aar' compile 'org.solovyev.android:android-common-views:1.1.18@aar' compile 'org.solovyev.android:android-common-menus:1.1.18@aar' - compile 'org.solovyev.android:android-common-preferences:1.1.18@aar' compile(project(':jscl')) { exclude(module: 'xercesImpl') } diff --git a/app/src/main/java/org/solovyev/android/prefs/AbstractDialogPreference.java b/app/src/main/java/org/solovyev/android/prefs/AbstractDialogPreference.java new file mode 100644 index 00000000..d5b6c5f1 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/AbstractDialogPreference.java @@ -0,0 +1,240 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.Context; +import android.preference.DialogPreference; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; +import org.solovyev.common.Objects; +import org.solovyev.common.text.Mapper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Base class for creating preferences with dialogs + * + * @param + */ +public abstract class AbstractDialogPreference extends DialogPreference { + + @Nonnull + protected final static String localNameSpace = "http://schemas.android.com/apk/res-auto"; + + @Nonnull + protected final static String androidns = "http://schemas.android.com/apk/res/android"; + + @Nonnull + private static final String TAG = AbstractDialogPreference.class.getSimpleName(); + @Nonnull + private final Context context; + @Nullable + private final String defaultStringValue; + private final boolean needValueText; + @Nonnull + private final Mapper mapper; + @Nullable + private TextView valueTextView; + @Nullable + private String valueText; + @Nullable + private View preferenceView; + @Nullable + private String description; + @Nullable + private T value; + @Nullable + private T defaultValue; + + public AbstractDialogPreference(Context context, AttributeSet attrs, @Nullable String defaultStringValue, boolean needValueText, @Nonnull Mapper mapper) { + super(context, attrs); + this.context = context; + this.defaultStringValue = defaultStringValue; + this.needValueText = needValueText; + this.mapper = mapper; + + final String defaultValueFromAttrs = attrs.getAttributeValue(androidns, "defaultValue"); + if (defaultValueFromAttrs != null) { + defaultValue = getMapper().parseValue(defaultValueFromAttrs); + } else if (defaultStringValue != null) { + defaultValue = getMapper().parseValue(defaultStringValue); + } else { + throw new IllegalArgumentException(); + } + + description = attrs.getAttributeValue(androidns, "dialogMessage"); + valueText = attrs.getAttributeValue(androidns, "text"); + } + + @Nullable + protected View getPreferenceView() { + return preferenceView; + } + + @Nullable + public T getValue() { + return value; + } + + public void setValue(@Nullable T value) { + this.value = value; + } + + @Override + @Nonnull + protected final LinearLayout onCreateDialogView() { + if (shouldPersist()) { + value = getPersistedValue(); + } + + final LinearLayout result = new LinearLayout(context); + result.setOrientation(LinearLayout.VERTICAL); + result.setPadding(6, 6, 6, 6); + + if (description != null) { + final TextView splashText = new TextView(context); + splashText.setText(description); + result.addView(splashText); + } + + if (needValueText) { + valueTextView = new TextView(context); + valueTextView.setGravity(Gravity.CENTER_HORIZONTAL); + valueTextView.setTextSize(32); + + final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + result.addView(valueTextView, params); + } + + preferenceView = createPreferenceView(context); + initPreferenceView(preferenceView, value); + + final LinearLayout.LayoutParams params = getParams(); + if (params != null) { + result.addView(preferenceView, params); + } else { + result.addView(preferenceView); + } + + return result; + } + + @Nullable + protected abstract LinearLayout.LayoutParams getParams(); + + @Override + protected void onSetInitialValue(boolean restore, Object defaultValue) { + super.onSetInitialValue(restore, defaultValue); + + if (restore) { + if (shouldPersist()) { + value = getPersistedValue(); + } else { + value = this.defaultValue; + } + } else { + value = (T) defaultValue; + if (shouldPersist()) { + persist(this.value); + } + } + } + + @Override + protected void onBindDialogView(View v) { + super.onBindDialogView(v); + if (this.preferenceView != null) { + initPreferenceView(this.preferenceView, value); + } + } + + /** + * Creates view which is responsible for changing preference value (for example, Spinner or EditText) + * + * @param context context + * @return view which changes the preference value + */ + @Nonnull + protected abstract View createPreferenceView(@Nonnull Context context); + + /** + * @param v view to be filled with initial data (the one which has been created with {@link #createPreferenceView} method) + * @param value current preference value + */ + protected abstract void initPreferenceView(@Nonnull View v, @Nullable T value); + + @Nullable + private T getPersistedValue() { + String persistedString = getPersistedString(defaultStringValue); + + if (Objects.areEqual(persistedString, defaultStringValue)) { + return defaultValue; + } else { + return getMapper().parseValue(persistedString); + } + } + + protected void persistValue(@Nullable T value) { + this.value = value; + if (!callChangeListener(value)) { + return; + } + if (!shouldPersist()) { + return; + } + persist(value); + } + + private void persist(@Nullable T value) { + if (value != null) { + final String toBePersistedString = getMapper().formatValue(value); + if (toBePersistedString != null) { + if (callChangeListener(toBePersistedString)) { + persistString(toBePersistedString); + } + } + } + } + + @Nullable + public String getValueText() { + return valueText; + } + + protected void updateValueText(@Nonnull String text) { + if (valueTextView != null) { + valueTextView.setText(text); + } + } + + @Nonnull + private Mapper getMapper() { + return this.mapper; + } +} diff --git a/app/src/main/java/org/solovyev/android/prefs/AbstractPreference.java b/app/src/main/java/org/solovyev/android/prefs/AbstractPreference.java new file mode 100644 index 00000000..0235d66c --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/AbstractPreference.java @@ -0,0 +1,130 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Base class for {@link Preference} implementation. Contains preference key and default value + * + * @param type of preference + */ +public abstract class AbstractPreference implements Preference { + + @Nonnull + private final String key; + + private final T defaultValue; + protected AbstractPreference(@Nonnull String key, @Nullable T defaultValue) { + this.key = key; + this.defaultValue = defaultValue; + } + + @Nonnull + public String getKey() { + return key; + } + + public T getDefaultValue() { + return defaultValue; + } + + @Override + public final T getPreference(@Nonnull SharedPreferences preferences) { + if (isSet(preferences)) { + return getPersistedValue(preferences); + } else { + return this.defaultValue; + } + } + + @Override + public T getPreferenceNoError(@Nonnull SharedPreferences preferences) { + if (isSet(preferences)) { + try { + return getPersistedValue(preferences); + } catch (RuntimeException e) { + return this.defaultValue; + } + } else { + return this.defaultValue; + } + } + + @Override + public void putDefault(@Nonnull SharedPreferences preferences) { + putPreference(preferences, this.defaultValue); + } + + @Override + public void putPreference(@Nonnull SharedPreferences preferences, @Nullable T value) { + if (value != null) { + final SharedPreferences.Editor editor = preferences.edit(); + putPersistedValue(editor, value); + editor.commit(); + } + } + + @Override + public boolean isSet(@Nonnull SharedPreferences preferences) { + return preferences.contains(this.key); + } + + @Override + public final boolean tryPutDefault(@Nonnull SharedPreferences preferences) { + final boolean result; + + if (isSet(preferences)) { + result = false; + } else { + putDefault(preferences); + result = true; + } + + return result; + } + + @Override + public final boolean isSameKey(@Nonnull String key) { + return this.key.equals(key); + } + + /** + * @param preferences preferences container + * @return preference value from preferences with key defined by {@link #getKey()} method + */ + @Nullable + protected abstract T getPersistedValue(@Nonnull SharedPreferences preferences); + + /** + * Method saved preference to preferences container editor + * + * @param editor editor in which value must be saved + * @param value value to be saved + */ + protected abstract void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull T value); + +} diff --git a/app/src/main/java/org/solovyev/android/prefs/BooleanPreference.java b/app/src/main/java/org/solovyev/android/prefs/BooleanPreference.java new file mode 100644 index 00000000..35a624ec --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/BooleanPreference.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class BooleanPreference extends AbstractPreference { + + private BooleanPreference(@Nonnull String key, @Nullable Boolean defaultValue) { + super(key, defaultValue); + } + + @Nonnull + public static BooleanPreference of(@Nonnull String key, @Nullable Boolean defaultValue) { + return new BooleanPreference(key, defaultValue); + } + + @Override + protected Boolean getPersistedValue(@Nonnull SharedPreferences preferences) { + return preferences.getBoolean(getKey(), false); + } + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull Boolean value) { + editor.putBoolean(getKey(), value); + } +} diff --git a/app/src/main/java/org/solovyev/android/prefs/CollectionSetPreference.java b/app/src/main/java/org/solovyev/android/prefs/CollectionSetPreference.java new file mode 100644 index 00000000..2dbd52ad --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/CollectionSetPreference.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; +import org.solovyev.common.text.Mapper; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +public abstract class CollectionSetPreference, T> extends AbstractPreference { + + @Nonnull + private final Mapper mapper; + + protected CollectionSetPreference(@Nonnull String id, @Nonnull C defaultValue, @Nonnull Mapper mapper) { + super(id, defaultValue); + this.mapper = mapper; + } + + @Override + protected C getPersistedValue(@Nonnull SharedPreferences preferences) { + final Set stringValues = preferences.getStringSet(getKey(), null); + + final C result = createCollection(stringValues.size()); + for (String stringValue : stringValues) { + result.add(mapper.parseValue(stringValue)); + } + + return result; + } + + @Nonnull + protected abstract C createCollection(int size); + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull C values) { + + final Set result = new HashSet(values.size()); + for (T value : values) { + result.add(mapper.formatValue(value)); + } + + editor.putStringSet(getKey(), result); + } +} diff --git a/app/src/main/java/org/solovyev/android/prefs/CollectionToStringPreference.java b/app/src/main/java/org/solovyev/android/prefs/CollectionToStringPreference.java new file mode 100644 index 00000000..0088d12a --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/CollectionToStringPreference.java @@ -0,0 +1,69 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; +import org.solovyev.common.text.ListMapper; +import org.solovyev.common.text.Mapper; +import org.solovyev.common.text.StringMapper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; + +public class CollectionToStringPreference, T> extends AbstractPreference { + + @Nonnull + private final Mapper mapper; + + private CollectionToStringPreference(@Nonnull String key, @Nullable C defaultValue, @Nonnull Mapper mapper) { + super(key, defaultValue); + this.mapper = mapper; + } + + @Nonnull + public static CollectionToStringPreference, T> forList(@Nonnull String key, @Nullable List defaultValue, @Nonnull Mapper> mapper) { + return new CollectionToStringPreference, T>(key, defaultValue, mapper); + } + + @Nonnull + public static CollectionToStringPreference, T> forTypedList(@Nonnull String key, @Nullable List defaultValue, @Nonnull Mapper mapper) { + return new CollectionToStringPreference, T>(key, defaultValue, ListMapper.newInstance(mapper)); + } + + @Nonnull + public static CollectionToStringPreference, String> forStringList(@Nonnull String key, @Nullable List defaultValue) { + return new CollectionToStringPreference, String>(key, defaultValue, ListMapper.newInstance(StringMapper.getInstance())); + } + + @Override + protected C getPersistedValue(@Nonnull SharedPreferences preferences) { + return mapper.parseValue(preferences.getString(getKey(), null)); + } + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull C values) { + editor.putString(getKey(), mapper.formatValue(values)); + } +} diff --git a/app/src/main/java/org/solovyev/android/prefs/FloatPreference.java b/app/src/main/java/org/solovyev/android/prefs/FloatPreference.java new file mode 100644 index 00000000..c9104ef8 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/FloatPreference.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class FloatPreference extends AbstractPreference { + + private FloatPreference(@Nonnull String key, @Nullable Float defaultValue) { + super(key, defaultValue); + } + + @Nonnull + public static FloatPreference of(@Nonnull String key, @Nullable Float defaultValue) { + return new FloatPreference(key, defaultValue); + } + + @Override + protected Float getPersistedValue(@Nonnull SharedPreferences preferences) { + return preferences.getFloat(getKey(), -1f); + } + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull Float value) { + editor.putFloat(getKey(), value); + } +} diff --git a/app/src/main/java/org/solovyev/android/prefs/HashSetPreference.java b/app/src/main/java/org/solovyev/android/prefs/HashSetPreference.java new file mode 100644 index 00000000..bba8a5d1 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/HashSetPreference.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import org.solovyev.common.text.EnumMapper; +import org.solovyev.common.text.Mapper; +import org.solovyev.common.text.StringMapper; + +import javax.annotation.Nonnull; +import java.util.HashSet; +import java.util.Set; + +public class HashSetPreference extends CollectionSetPreference, T> { + + private HashSetPreference(@Nonnull String id, @Nonnull Set defaultValue, @Nonnull Mapper mapper) { + super(id, defaultValue, mapper); + } + + @Nonnull + public static HashSetPreference ofStrings(@Nonnull String key, @Nonnull Set defaultValue) { + return new HashSetPreference(key, defaultValue, StringMapper.getInstance()); + } + + @Nonnull + public static HashSetPreference ofTypedValues(@Nonnull String key, @Nonnull Set defaultValue, @Nonnull Mapper parser) { + return new HashSetPreference(key, defaultValue, parser); + } + + @Nonnull + public static HashSetPreference ofEnums(@Nonnull String id, @Nonnull Set defaultValue, @Nonnull Class enumType) { + return new HashSetPreference(id, defaultValue, EnumMapper.of(enumType)); + } + + @Nonnull + @Override + protected Set createCollection(int size) { + return new HashSet(size); + } +} diff --git a/app/src/main/java/org/solovyev/android/prefs/IntegerPreference.java b/app/src/main/java/org/solovyev/android/prefs/IntegerPreference.java new file mode 100644 index 00000000..0cf317a9 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/IntegerPreference.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class IntegerPreference extends AbstractPreference { + + private IntegerPreference(@Nonnull String key, @Nullable Integer defaultValue) { + super(key, defaultValue); + } + + @Nonnull + public static IntegerPreference of(@Nonnull String key, @Nullable Integer defaultValue) { + return new IntegerPreference(key, defaultValue); + } + + @Override + protected Integer getPersistedValue(@Nonnull SharedPreferences preferences) { + return preferences.getInt(getKey(), -1); + } + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull Integer value) { + editor.putInt(getKey(), value); + } + +} diff --git a/app/src/main/java/org/solovyev/android/prefs/LocalePreference.java b/app/src/main/java/org/solovyev/android/prefs/LocalePreference.java new file mode 100644 index 00000000..e0487e15 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/LocalePreference.java @@ -0,0 +1,155 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; +import org.solovyev.common.text.Mapper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Locale; +import java.util.StringTokenizer; + +public class LocalePreference implements Preference { + + @Nonnull + private final StringPreference stringPreference; + + private LocalePreference(@Nonnull String id, @Nullable Locale defaultValue, @Nonnull Mapper localeMapper) { + this.stringPreference = new StringPreference(id, defaultValue, localeMapper); + } + + private LocalePreference(@Nonnull String id, @Nullable Locale defaultValue) { + this.stringPreference = new StringPreference(id, defaultValue, DefaultLocaleMapper.getInstance()); + } + + @Nonnull + public static LocalePreference of(@Nonnull String id, @Nullable Locale defaultValue, @Nonnull Mapper localeMapper) { + return new LocalePreference(id, defaultValue, localeMapper); + } + + @Nonnull + public static LocalePreference of(@Nonnull String id, @Nullable Locale defaultValue) { + return new LocalePreference(id, defaultValue); + } + + @Override + @Nonnull + public String getKey() { + return stringPreference.getKey(); + } + + @Override + public Locale getDefaultValue() { + return stringPreference.getDefaultValue(); + } + + @Override + public Locale getPreference(@Nonnull SharedPreferences preferences) { + return stringPreference.getPreference(preferences); + } + + @Override + public Locale getPreferenceNoError(@Nonnull SharedPreferences preferences) { + return stringPreference.getPreferenceNoError(preferences); + } + + @Override + public void putDefault(@Nonnull SharedPreferences preferences) { + stringPreference.putDefault(preferences); + } + + @Override + public void putPreference(@Nonnull SharedPreferences preferences, @Nullable Locale value) { + stringPreference.putPreference(preferences, value); + } + + @Override + public boolean isSet(@Nonnull SharedPreferences preferences) { + return stringPreference.isSet(preferences); + } + + @Override + public boolean tryPutDefault(@Nonnull SharedPreferences preferences) { + return stringPreference.tryPutDefault(preferences); + } + + @Override + public boolean isSameKey(@Nonnull String key) { + return stringPreference.isSameKey(key); + } + + /* + ********************************************************************** + * + * STATIC + * + ********************************************************************** + */ + + private static final class DefaultLocaleMapper implements Mapper { + + @Nonnull + private static final String delimiter = ";"; + + @Nonnull + private static Mapper instance = new DefaultLocaleMapper(); + + private DefaultLocaleMapper() { + } + + @Nonnull + public static Mapper getInstance() { + return instance; + } + + @Override + public String formatValue(@Nullable Locale locale) throws IllegalArgumentException { + assert locale != null; + return locale.getLanguage() + delimiter + locale.getCountry() + delimiter + locale.getVariant(); + } + + @Override + public Locale parseValue(@Nullable String s) throws IllegalArgumentException { + final StringTokenizer st = new StringTokenizer(s, delimiter, false); + + final String language = st.nextToken(); + + final String country; + if (st.hasMoreTokens()) { + country = st.nextToken(); + } else { + country = ""; + } + + final String variant; + if (st.hasMoreTokens()) { + variant = st.nextToken(); + } else { + variant = ""; + } + + return new Locale(language, country, variant); + } + } +} diff --git a/app/src/main/java/org/solovyev/android/prefs/LongPreference.java b/app/src/main/java/org/solovyev/android/prefs/LongPreference.java new file mode 100644 index 00000000..5bd00377 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/LongPreference.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class LongPreference extends AbstractPreference { + + private LongPreference(@Nonnull String key, @Nullable Long defaultValue) { + super(key, defaultValue); + } + + @Nonnull + public static LongPreference of(@Nonnull String key, @Nullable Long defaultValue) { + return new LongPreference(key, defaultValue); + } + + @Override + protected Long getPersistedValue(@Nonnull SharedPreferences preferences) { + return preferences.getLong(getKey(), -1); + } + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull Long value) { + editor.putLong(getKey(), value); + } +} diff --git a/app/src/main/java/org/solovyev/android/prefs/NumberIntervalPreference.java b/app/src/main/java/org/solovyev/android/prefs/NumberIntervalPreference.java new file mode 100644 index 00000000..0dabe873 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/NumberIntervalPreference.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; +import org.solovyev.common.interval.Interval; +import org.solovyev.common.text.Mapper; +import org.solovyev.common.text.NumberIntervalMapper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public final class NumberIntervalPreference> extends AbstractPreference> { + + @Nonnull + private final Mapper> mapper; + + private NumberIntervalPreference(@Nonnull String key, @Nullable Interval defaultValue, @Nonnull Class clazz) { + super(key, defaultValue); + this.mapper = NumberIntervalMapper.of(clazz); + + } + + @Nonnull + public static > NumberIntervalPreference of(@Nonnull String key, @Nullable Interval defaultValue, @Nonnull Class clazz) { + return new NumberIntervalPreference(key, defaultValue, clazz); + } + + @Override + protected Interval getPersistedValue(@Nonnull SharedPreferences preferences) { + final String result = preferences.getString(getKey(), null); + if (result == null) { + return null; + } else { + return mapper.parseValue(result); + } + } + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull Interval value) { + editor.putString(getKey(), mapper.formatValue(value)); + } + +} diff --git a/app/src/main/java/org/solovyev/android/prefs/NumberToStringPreference.java b/app/src/main/java/org/solovyev/android/prefs/NumberToStringPreference.java new file mode 100644 index 00000000..8e102412 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/NumberToStringPreference.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; +import org.solovyev.common.text.Mapper; +import org.solovyev.common.text.NumberMapper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class NumberToStringPreference extends AbstractPreference { + + @Nonnull + private final Mapper mapper; + + private NumberToStringPreference(@Nonnull String key, @Nullable N defaultValue, @Nonnull Class clazz) { + super(key, defaultValue); + + this.mapper = NumberMapper.of(clazz); + } + + @Nonnull + public static NumberToStringPreference of(@Nonnull String key, @Nullable N defaultValue, @Nonnull Class clazz) { + return new NumberToStringPreference(key, defaultValue, clazz); + } + + @Override + protected N getPersistedValue(@Nonnull SharedPreferences preferences) { + return mapper.parseValue(preferences.getString(getKey(), "0")); + } + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull N value) { + editor.putString(getKey(), mapper.formatValue(value)); + } + +} diff --git a/app/src/main/java/org/solovyev/android/prefs/Preference.java b/app/src/main/java/org/solovyev/android/prefs/Preference.java new file mode 100644 index 00000000..230a9cfb --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/Preference.java @@ -0,0 +1,102 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Class for working with android preferences: can save and load preferences, convert them to custom java objects + * and use default value; + * + * @param type of java object preference + */ +public interface Preference { + + /** + * Method returns key of preference used in android: the key with which current preference is saved in persistence + * + * @return android preference key + */ + @Nonnull + String getKey(); + + /** + * @return default preference value, may be null + */ + T getDefaultValue(); + + /** + * NOTE: this method can throw runtime exceptions if errors occurred while extracting preferences values + * + * @param preferences application preferences + * @return value from preference, default value if no value in preference was found + */ + T getPreference(@Nonnull SharedPreferences preferences); + + /** + * NOTE: this method SHOULD not throw any runtime exceptions BUT return default value if any error occurred + * + * @param preferences application preferences + * @return value from preference, default value if no value in preference was found or error occurred + */ + T getPreferenceNoError(@Nonnull SharedPreferences preferences); + + /** + * Method puts (saves) preference represented by value in preferences container + * + * @param preferences preferences container + * @param value value to be saved + */ + void putPreference(@Nonnull SharedPreferences preferences, @Nullable T value); + + /** + * Method saves default value in preferences container. + * Should behave exactly as p.putPreference(preferences, p.getDefaultValue()) + * + * @param preferences preferences container + */ + void putDefault(@Nonnull SharedPreferences preferences); + + /** + * @param preferences preferences container + * @return true if any value is saved in preferences container, false - otherwise + */ + boolean isSet(@Nonnull SharedPreferences preferences); + + /** + * Method applies default value to preference only if explicit value is not set + * + * @param preferences preferences container + * @return true if default values have been applied, false otherwise + */ + boolean tryPutDefault(@Nonnull SharedPreferences preferences); + + /** + * @param key preference key + * @return true if current preferences has the same key + */ + boolean isSameKey(@Nonnull String key); +} diff --git a/app/src/main/java/org/solovyev/android/prefs/SeekBarPreference.java b/app/src/main/java/org/solovyev/android/prefs/SeekBarPreference.java new file mode 100644 index 00000000..cccd87c8 --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/SeekBarPreference.java @@ -0,0 +1,114 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.SeekBar; +import org.solovyev.common.text.NumberMapper; + +import javax.annotation.Nonnull; + + +/* The following code was written by Matthew Wiggins + * and is released under the APACHE 2.0 license + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +public class SeekBarPreference extends AbstractDialogPreference implements SeekBar.OnSeekBarChangeListener { + + private int max = 0; + + public SeekBarPreference(Context context, AttributeSet attrs) { + super(context, attrs, "50", true, NumberMapper.of(Integer.class)); + + max = attrs.getAttributeIntValue(androidns, "max", 100); + } + + @Override + protected LinearLayout.LayoutParams getParams() { + return new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + } + + @Nonnull + @Override + protected View createPreferenceView(@Nonnull Context context) { + final SeekBar result = new SeekBar(context); + + result.setOnSeekBarChangeListener(this); + + return result; + } + + @Override + protected void initPreferenceView(@Nonnull View v, Integer value) { + ((SeekBar) v).setMax(max); + if (value != null) { + ((SeekBar) v).setProgress(value); + setValueText(value); + } + } + + public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) { + setValueText(value); + + persistValue(value); + } + + private void setValueText(int value) { + String t = String.valueOf(value); + final String valueText = getValueText(); + updateValueText(valueText == null ? t : t.concat(valueText)); + } + + public void onStartTrackingTouch(SeekBar seek) { + } + + public void onStopTrackingTouch(SeekBar seek) { + } + + public int getMax() { + return max; + } + + public void setMax(int max) { + this.max = max; + } + + public int getProgress() { + final Integer value = getValue(); + return value == null ? 0 : value; + } + + public void setProgress(int progress) { + setValue(progress); + final View preferenceView = getPreferenceView(); + if (preferenceView != null) { + ((SeekBar) preferenceView).setProgress(progress); + } + } +} + diff --git a/app/src/main/java/org/solovyev/android/prefs/StringPreference.java b/app/src/main/java/org/solovyev/android/prefs/StringPreference.java new file mode 100644 index 00000000..0341ea4d --- /dev/null +++ b/app/src/main/java/org/solovyev/android/prefs/StringPreference.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013 serso aka se.solovyev + * + * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Contact details + * + * Email: se.solovyev@gmail.com + * Site: http://se.solovyev.org + */ + +package org.solovyev.android.prefs; + +import android.content.SharedPreferences; +import org.solovyev.common.text.EnumMapper; +import org.solovyev.common.text.Mapper; +import org.solovyev.common.text.StringMapper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * {@link Preference} implementation which uses {@link String} way of storing object in persistence. + * This class provides methods for mapping real java objects to String and vice versa. + * + * @param + */ +public final class StringPreference extends AbstractPreference { + + @Nonnull + private final Mapper mapper; + + public StringPreference(@Nonnull String key, @Nullable T defaultValue, @Nonnull Mapper mapper) { + super(key, defaultValue); + this.mapper = mapper; + } + + @Nonnull + public static StringPreference of(@Nonnull String key, @Nullable String defaultValue) { + return new StringPreference(key, defaultValue, StringMapper.getInstance()); + } + + @Nonnull + public static StringPreference ofTypedValue(@Nonnull String key, @Nullable String defaultValue, @Nonnull Mapper mapper) { + return new StringPreference(key, mapper.parseValue(defaultValue), mapper); + } + + @Nonnull + public static StringPreference ofEnum(@Nonnull String key, @Nullable T defaultValue, @Nonnull Class enumType) { + return new StringPreference(key, defaultValue, EnumMapper.of(enumType)); + } + + @Override + protected T getPersistedValue(@Nonnull SharedPreferences preferences) { + return mapper.parseValue(preferences.getString(getKey(), null)); + } + + @Override + protected void putPersistedValue(@Nonnull SharedPreferences.Editor editor, @Nonnull T value) { + editor.putString(getKey(), mapper.formatValue(value)); + } +} diff --git a/app/src/main/res/values/prefs_attributes.xml b/app/src/main/res/values/prefs_attributes.xml new file mode 100644 index 00000000..3ad349ec --- /dev/null +++ b/app/src/main/res/values/prefs_attributes.xml @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file