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.

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

mercurial