summaryrefslogtreecommitdiffstats
path: root/mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java')
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java271
1 files changed, 271 insertions, 0 deletions
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java
new file mode 100644
index 000000000..5749bf29d
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java
@@ -0,0 +1,271 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.preferences;
+
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.GeckoSharedPrefs;
+import org.mozilla.gecko.util.PrefUtils;
+import org.mozilla.gecko.util.ThreadUtils;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.TypedArray;
+import android.content.SharedPreferences;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+
+import java.util.HashSet;
+import java.util.Set;
+
+class MultiChoicePreference extends DialogPreference implements DialogInterface.OnMultiChoiceClickListener {
+ private static final String LOGTAG = "GeckoMultiChoicePreference";
+
+ private boolean mValues[];
+ private boolean mPrevValues[];
+ private CharSequence mEntryValues[];
+ private CharSequence mEntries[];
+ private CharSequence mInitialValues[];
+
+ public MultiChoicePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiChoicePreference);
+ mEntries = a.getTextArray(R.styleable.MultiChoicePreference_entries);
+ mEntryValues = a.getTextArray(R.styleable.MultiChoicePreference_entryValues);
+ mInitialValues = a.getTextArray(R.styleable.MultiChoicePreference_initialValues);
+ a.recycle();
+
+ loadPersistedValues();
+ }
+
+ public MultiChoicePreference(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Sets the human-readable entries to be shown in the list. This will be
+ * shown in subsequent dialogs.
+ * <p>
+ * Each entry must have a corresponding index in
+ * {@link #setEntryValues(CharSequence[])} and
+ * {@link #setInitialValues(CharSequence[])}.
+ *
+ * @param entries The entries.
+ */
+ public void setEntries(CharSequence[] entries) {
+ mEntries = entries.clone();
+ }
+
+ /**
+ * @param entriesResId The entries array as a resource.
+ */
+ public void setEntries(int entriesResId) {
+ setEntries(getContext().getResources().getTextArray(entriesResId));
+ }
+
+ /**
+ * Sets the preference values for preferences shown in the list.
+ *
+ * @param entryValues The entry values.
+ */
+ public void setEntryValues(CharSequence[] entryValues) {
+ mEntryValues = entryValues.clone();
+ loadPersistedValues();
+ }
+
+ /**
+ * Entry values define a separate pref for each row in the dialog.
+ *
+ * @param entryValuesResId The entryValues array as a resource.
+ */
+ public void setEntryValues(int entryValuesResId) {
+ setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
+ }
+
+ /**
+ * The array of initial entry values in this list. Each entryValue
+ * corresponds to an entryKey. These values are used if a) the preference
+ * isn't persisted, or b) the preference is persisted but hasn't yet been
+ * set.
+ *
+ * @param initialValues The entry values
+ */
+ public void setInitialValues(CharSequence[] initialValues) {
+ mInitialValues = initialValues.clone();
+ loadPersistedValues();
+ }
+
+ /**
+ * @param initialValuesResId The initialValues array as a resource.
+ */
+ public void setInitialValues(int initialValuesResId) {
+ setInitialValues(getContext().getResources().getTextArray(initialValuesResId));
+ }
+
+ /**
+ * The list of translated strings corresponding to each preference.
+ *
+ * @return The array of entries.
+ */
+ public CharSequence[] getEntries() {
+ return mEntries.clone();
+ }
+
+ /**
+ * The list of values corresponding to each preference.
+ *
+ * @return The array of values.
+ */
+ public CharSequence[] getEntryValues() {
+ return mEntryValues.clone();
+ }
+
+ /**
+ * The list of initial values for each preference. Each string in this list
+ * should be either "true" or "false".
+ *
+ * @return The array of initial values.
+ */
+ public CharSequence[] getInitialValues() {
+ return mInitialValues.clone();
+ }
+
+ public void setValue(final int i, final boolean value) {
+ mValues[i] = value;
+ mPrevValues = mValues.clone();
+ }
+
+ /**
+ * The list of values for each preference. These values are updated after
+ * the dialog has been displayed.
+ *
+ * @return The array of values.
+ */
+ public Set<String> getValues() {
+ final Set<String> values = new HashSet<String>();
+
+ if (mValues == null) {
+ return values;
+ }
+
+ for (int i = 0; i < mValues.length; i++) {
+ if (mValues[i]) {
+ values.add(mEntryValues[i].toString());
+ }
+ }
+
+ return values;
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which, boolean val) {
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(Builder builder) {
+ if (mEntries == null || mInitialValues == null || mEntryValues == null) {
+ throw new IllegalStateException(
+ "MultiChoicePreference requires entries, entryValues, and initialValues arrays.");
+ }
+
+ if (mEntries.length != mEntryValues.length || mEntries.length != mInitialValues.length) {
+ throw new IllegalStateException(
+ "MultiChoicePreference entries, entryValues, and initialValues arrays must be the same length");
+ }
+
+ builder.setMultiChoiceItems(mEntries, mValues, this);
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ if (mPrevValues == null || mInitialValues == null) {
+ // Initialization is done asynchronously, so these values may not
+ // have been set before the dialog was closed.
+ return;
+ }
+
+ if (!positiveResult) {
+ // user cancelled; reset checkbox values to their previous state
+ mValues = mPrevValues.clone();
+ return;
+ }
+
+ mPrevValues = mValues.clone();
+
+ if (!callChangeListener(getValues())) {
+ return;
+ }
+
+ persist();
+ }
+
+ /* Persists the current data stored by this pref to SharedPreferences. */
+ public boolean persist() {
+ if (isPersistent()) {
+ final SharedPreferences.Editor edit = GeckoSharedPrefs.forProfile(getContext()).edit();
+ final boolean res = persist(edit);
+ edit.apply();
+ return res;
+ }
+
+ return false;
+ }
+
+ /* Internal persist method. Take an edit so that multiple prefs can be persisted in a single commit. */
+ protected boolean persist(SharedPreferences.Editor edit) {
+ if (isPersistent()) {
+ Set<String> vals = getValues();
+ PrefUtils.putStringSet(edit, getKey(), vals).apply();;
+ return true;
+ }
+
+ return false;
+ }
+
+ /* Returns a list of EntryValues that are currently enabled. */
+ public Set<String> getPersistedStrings(Set<String> defaultVal) {
+ if (!isPersistent()) {
+ return defaultVal;
+ }
+
+ final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getContext());
+ return PrefUtils.getStringSet(prefs, getKey(), defaultVal);
+ }
+
+ /**
+ * Loads persistent prefs from shared preferences. If the preferences
+ * aren't persistent or haven't yet been stored, they will be set to their
+ * initial values.
+ */
+ protected void loadPersistedValues() {
+ final int entryCount = mInitialValues.length;
+ mValues = new boolean[entryCount];
+
+ if (entryCount != mEntries.length || entryCount != mEntryValues.length) {
+ throw new IllegalStateException(
+ "MultiChoicePreference entryValues and initialValues arrays must be the same length");
+ }
+
+ ThreadUtils.postToBackgroundThread(new Runnable() {
+ @Override
+ public void run() {
+ final Set<String> stringVals = getPersistedStrings(null);
+
+ for (int i = 0; i < entryCount; i++) {
+ if (stringVals != null) {
+ mValues[i] = stringVals.contains(mEntryValues[i]);
+ } else {
+ final boolean defaultVal = mInitialValues[i].equals("true");
+ mValues[i] = defaultVal;
+ }
+ }
+
+ mPrevValues = mValues.clone();
+ }
+ });
+ }
+}