mobile/android/base/preferences/MultiChoicePreference.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 package org.mozilla.gecko.preferences;
michael@0 7
michael@0 8 import org.mozilla.gecko.R;
michael@0 9 import org.mozilla.gecko.GeckoSharedPrefs;
michael@0 10 import org.mozilla.gecko.util.ThreadUtils;
michael@0 11
michael@0 12 import android.app.AlertDialog;
michael@0 13 import android.app.AlertDialog.Builder;
michael@0 14 import android.content.Context;
michael@0 15 import android.content.DialogInterface;
michael@0 16 import android.content.res.TypedArray;
michael@0 17 import android.preference.DialogPreference;
michael@0 18 import android.util.AttributeSet;
michael@0 19 import android.widget.Button;
michael@0 20
michael@0 21 class MultiChoicePreference extends DialogPreference {
michael@0 22 private static final String LOGTAG = "GeckoMultiChoicePreference";
michael@0 23
michael@0 24 private boolean mValues[];
michael@0 25 private boolean mPrevValues[];
michael@0 26 private CharSequence mEntryKeys[];
michael@0 27 private CharSequence mEntries[];
michael@0 28 private CharSequence mInitialValues[];
michael@0 29
michael@0 30 public MultiChoicePreference(Context context, AttributeSet attrs) {
michael@0 31 super(context, attrs);
michael@0 32
michael@0 33 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiChoicePreference);
michael@0 34 mEntries = a.getTextArray(R.styleable.MultiChoicePreference_entries);
michael@0 35 mEntryKeys = a.getTextArray(R.styleable.MultiChoicePreference_entryKeys);
michael@0 36 mInitialValues = a.getTextArray(R.styleable.MultiChoicePreference_initialValues);
michael@0 37 a.recycle();
michael@0 38
michael@0 39 loadPersistedValues();
michael@0 40 }
michael@0 41
michael@0 42 public MultiChoicePreference(Context context) {
michael@0 43 this(context, null);
michael@0 44 }
michael@0 45
michael@0 46 /**
michael@0 47 * Sets the human-readable entries to be shown in the list. This will be
michael@0 48 * shown in subsequent dialogs.
michael@0 49 * <p>
michael@0 50 * Each entry must have a corresponding index in
michael@0 51 * {@link #setEntryKeys(CharSequence[])} and
michael@0 52 * {@link #setInitialValues(CharSequence[])}.
michael@0 53 *
michael@0 54 * @param entries The entries.
michael@0 55 */
michael@0 56 public void setEntries(CharSequence[] entries) {
michael@0 57 mEntries = entries.clone();
michael@0 58 }
michael@0 59
michael@0 60 /**
michael@0 61 * @param entriesResId The entries array as a resource.
michael@0 62 */
michael@0 63 public void setEntries(int entriesResId) {
michael@0 64 setEntries(getContext().getResources().getTextArray(entriesResId));
michael@0 65 }
michael@0 66
michael@0 67 /**
michael@0 68 * Sets the preference keys for preferences shown in the list.
michael@0 69 *
michael@0 70 * @param entryKeys The entry keys.
michael@0 71 */
michael@0 72 public void setEntryKeys(CharSequence[] entryKeys) {
michael@0 73 mEntryKeys = entryKeys.clone();
michael@0 74 loadPersistedValues();
michael@0 75 }
michael@0 76
michael@0 77 /**
michael@0 78 * @param entryKeysResId The entryKeys array as a resource.
michael@0 79 */
michael@0 80 public void setEntryKeys(int entryKeysResId) {
michael@0 81 setEntryKeys(getContext().getResources().getTextArray(entryKeysResId));
michael@0 82 }
michael@0 83
michael@0 84 /**
michael@0 85 * The array of initial entry values in this list. Each entryValue
michael@0 86 * corresponds to an entryKey. These values are used if a) the preference
michael@0 87 * isn't persisted, or b) the preference is persisted but hasn't yet been
michael@0 88 * set.
michael@0 89 *
michael@0 90 * @param initialValues The entry values
michael@0 91 */
michael@0 92 public void setInitialValues(CharSequence[] initialValues) {
michael@0 93 mInitialValues = initialValues.clone();
michael@0 94 loadPersistedValues();
michael@0 95 }
michael@0 96
michael@0 97 /**
michael@0 98 * @param initialValuesResId The initialValues array as a resource.
michael@0 99 */
michael@0 100 public void setInitialValues(int initialValuesResId) {
michael@0 101 setInitialValues(getContext().getResources().getTextArray(initialValuesResId));
michael@0 102 }
michael@0 103
michael@0 104 /**
michael@0 105 * The list of translated strings corresponding to each preference.
michael@0 106 *
michael@0 107 * @return The array of entries.
michael@0 108 */
michael@0 109 public CharSequence[] getEntries() {
michael@0 110 return mEntries.clone();
michael@0 111 }
michael@0 112
michael@0 113 /**
michael@0 114 * The list of keys corresponding to each preference.
michael@0 115 *
michael@0 116 * @return The array of keys.
michael@0 117 */
michael@0 118 public CharSequence[] getEntryKeys() {
michael@0 119 return mEntryKeys.clone();
michael@0 120 }
michael@0 121
michael@0 122 /**
michael@0 123 * The list of initial values for each preference. Each string in this list
michael@0 124 * should be either "true" or "false".
michael@0 125 *
michael@0 126 * @return The array of initial values.
michael@0 127 */
michael@0 128 public CharSequence[] getInitialValues() {
michael@0 129 return mInitialValues.clone();
michael@0 130 }
michael@0 131
michael@0 132 /**
michael@0 133 * The list of values for each preference. These values are updated after
michael@0 134 * the dialog has been displayed.
michael@0 135 *
michael@0 136 * @return The array of values.
michael@0 137 */
michael@0 138 public boolean[] getValues() {
michael@0 139 return mValues.clone();
michael@0 140 }
michael@0 141
michael@0 142 @Override
michael@0 143 protected void onPrepareDialogBuilder(Builder builder) {
michael@0 144 if (mEntries == null || mEntryKeys == null || mInitialValues == null) {
michael@0 145 throw new IllegalStateException(
michael@0 146 "MultiChoicePreference requires entries, entryKeys, and initialValues arrays.");
michael@0 147 }
michael@0 148
michael@0 149 if (mEntries.length != mEntryKeys.length || mEntryKeys.length != mInitialValues.length) {
michael@0 150 throw new IllegalStateException(
michael@0 151 "MultiChoicePreference entries, entryKeys, and initialValues arrays must be the same length");
michael@0 152 }
michael@0 153
michael@0 154 builder.setMultiChoiceItems(mEntries, mValues, new DialogInterface.OnMultiChoiceClickListener() {
michael@0 155 @Override
michael@0 156 public void onClick(DialogInterface dialog, int which, boolean val) {
michael@0 157 // mValues is automatically updated when checkboxes are clicked
michael@0 158
michael@0 159 // enable positive button only if at least one item is checked
michael@0 160 boolean enabled = false;
michael@0 161 for (int i = 0; i < mValues.length; i++) {
michael@0 162 if (mValues[i]) {
michael@0 163 enabled = true;
michael@0 164 break;
michael@0 165 }
michael@0 166 }
michael@0 167 Button button = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
michael@0 168 if (button.isEnabled() != enabled)
michael@0 169 button.setEnabled(enabled);
michael@0 170 }
michael@0 171 });
michael@0 172 }
michael@0 173
michael@0 174 @Override
michael@0 175 protected void onDialogClosed(boolean positiveResult) {
michael@0 176 if (mPrevValues == null || mInitialValues == null) {
michael@0 177 // Initialization is done asynchronously, so these values may not
michael@0 178 // have been set before the dialog was closed.
michael@0 179 return;
michael@0 180 }
michael@0 181
michael@0 182 if (!positiveResult) {
michael@0 183 // user cancelled; reset checkbox values to their previous state
michael@0 184 mValues = mPrevValues.clone();
michael@0 185 return;
michael@0 186 } else {
michael@0 187 mPrevValues = mValues.clone();
michael@0 188 }
michael@0 189
michael@0 190 ThreadUtils.postToBackgroundThread(new Runnable() {
michael@0 191 @Override
michael@0 192 public void run() {
michael@0 193 for (int i = 0; i < mEntryKeys.length; i++) {
michael@0 194 String key = mEntryKeys[i].toString();
michael@0 195 persistBoolean(key, mValues[i]);
michael@0 196 }
michael@0 197 }
michael@0 198 });
michael@0 199 }
michael@0 200
michael@0 201 protected boolean persistBoolean(String key, boolean value) {
michael@0 202 if (isPersistent()) {
michael@0 203 if (value == getPersistedBoolean(!value)) {
michael@0 204 // It's already there, so the same as persisting
michael@0 205 return true;
michael@0 206 }
michael@0 207
michael@0 208 GeckoSharedPrefs.forApp(getContext())
michael@0 209 .edit().putBoolean(key, value).commit();
michael@0 210 return true;
michael@0 211 }
michael@0 212 return false;
michael@0 213 }
michael@0 214
michael@0 215 protected boolean getPersistedBoolean(String key, boolean defaultReturnValue) {
michael@0 216 if (!isPersistent())
michael@0 217 return defaultReturnValue;
michael@0 218
michael@0 219 return GeckoSharedPrefs.forApp(getContext())
michael@0 220 .getBoolean(key, defaultReturnValue);
michael@0 221 }
michael@0 222
michael@0 223 /**
michael@0 224 * Loads persistent prefs from shared preferences. If the preferences
michael@0 225 * aren't persistent or haven't yet been stored, they will be set to their
michael@0 226 * initial values.
michael@0 227 */
michael@0 228 private void loadPersistedValues() {
michael@0 229 if (mEntryKeys == null || mInitialValues == null)
michael@0 230 return;
michael@0 231
michael@0 232 final int entryCount = mEntryKeys.length;
michael@0 233 if (entryCount != mEntries.length || entryCount != mInitialValues.length) {
michael@0 234 throw new IllegalStateException(
michael@0 235 "MultiChoicePreference entryKeys and initialValues arrays must be the same length");
michael@0 236 }
michael@0 237
michael@0 238 mValues = new boolean[entryCount];
michael@0 239 ThreadUtils.postToBackgroundThread(new Runnable() {
michael@0 240 @Override
michael@0 241 public void run() {
michael@0 242 for (int i = 0; i < entryCount; i++) {
michael@0 243 String key = mEntryKeys[i].toString();
michael@0 244 boolean initialValue = mInitialValues[i].equals("true");
michael@0 245 mValues[i] = getPersistedBoolean(key, initialValue);
michael@0 246 }
michael@0 247 mPrevValues = mValues.clone();
michael@0 248 }
michael@0 249 });
michael@0 250 }
michael@0 251 }

mercurial