2012-06-26 23:15:23 -07:00
|
|
|
/* -*- 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;
|
|
|
|
|
2013-03-15 03:52:53 -07:00
|
|
|
import org.mozilla.gecko.util.ThreadUtils;
|
|
|
|
|
2012-07-18 10:11:26 -07:00
|
|
|
import android.app.AlertDialog;
|
2012-06-26 23:15:23 -07:00
|
|
|
import android.app.AlertDialog.Builder;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.DialogInterface;
|
2012-07-27 17:53:54 -07:00
|
|
|
import android.content.res.TypedArray;
|
2012-06-26 23:15:23 -07:00
|
|
|
import android.preference.DialogPreference;
|
|
|
|
import android.preference.PreferenceManager;
|
|
|
|
import android.util.AttributeSet;
|
2012-07-18 10:11:26 -07:00
|
|
|
import android.widget.Button;
|
2012-06-26 23:15:23 -07:00
|
|
|
|
|
|
|
class MultiChoicePreference extends DialogPreference {
|
|
|
|
private static final String LOGTAG = "GeckoMultiChoicePreference";
|
|
|
|
|
|
|
|
private boolean mValues[];
|
|
|
|
private boolean mPrevValues[];
|
|
|
|
private CharSequence mEntryKeys[];
|
|
|
|
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);
|
|
|
|
mEntryKeys = a.getTextArray(R.styleable.MultiChoicePreference_entryKeys);
|
|
|
|
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 #setEntryKeys(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 keys for preferences shown in the list.
|
|
|
|
*
|
|
|
|
* @param entryKeys The entry keys.
|
|
|
|
*/
|
|
|
|
public void setEntryKeys(CharSequence[] entryKeys) {
|
|
|
|
mEntryKeys = entryKeys.clone();
|
|
|
|
loadPersistedValues();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param entryKeysResId The entryKeys array as a resource.
|
|
|
|
*/
|
|
|
|
public void setEntryKeys(int entryKeysResId) {
|
|
|
|
setEntryKeys(getContext().getResources().getTextArray(entryKeysResId));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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 keys corresponding to each preference.
|
|
|
|
*
|
|
|
|
* @return The array of keys.
|
|
|
|
*/
|
|
|
|
public CharSequence[] getEntryKeys() {
|
|
|
|
return mEntryKeys.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();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The list of values for each preference. These values are updated after
|
|
|
|
* the dialog has been displayed.
|
|
|
|
*
|
|
|
|
* @return The array of values.
|
|
|
|
*/
|
|
|
|
public boolean[] getValues() {
|
|
|
|
return mValues.clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPrepareDialogBuilder(Builder builder) {
|
|
|
|
if (mEntries == null || mEntryKeys == null || mInitialValues == null) {
|
|
|
|
throw new IllegalStateException(
|
|
|
|
"MultiChoicePreference requires entries, entryKeys, and initialValues arrays.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mEntries.length != mEntryKeys.length || mEntryKeys.length != mInitialValues.length) {
|
|
|
|
throw new IllegalStateException(
|
|
|
|
"MultiChoicePreference entries, entryKeys, and initialValues arrays must be the same length");
|
|
|
|
}
|
|
|
|
|
|
|
|
builder.setMultiChoiceItems(mEntries, mValues, new DialogInterface.OnMultiChoiceClickListener() {
|
2013-02-26 21:48:00 -08:00
|
|
|
@Override
|
2012-06-26 23:15:23 -07:00
|
|
|
public void onClick(DialogInterface dialog, int which, boolean val) {
|
|
|
|
// mValues is automatically updated when checkboxes are clicked
|
2012-07-18 10:11:26 -07:00
|
|
|
|
|
|
|
// enable positive button only if at least one item is checked
|
|
|
|
boolean enabled = false;
|
|
|
|
for (int i = 0; i < mValues.length; i++) {
|
|
|
|
if (mValues[i]) {
|
|
|
|
enabled = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Button button = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
|
|
|
|
if (button.isEnabled() != enabled)
|
|
|
|
button.setEnabled(enabled);
|
2012-06-26 23:15:23 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onDialogClosed(boolean positiveResult) {
|
2012-10-18 12:28:27 -07:00
|
|
|
if (mPrevValues == null || mInitialValues == null) {
|
|
|
|
// Initialization is done asynchronously, so these values may not
|
|
|
|
// have been set before the dialog was closed.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-06-26 23:15:23 -07:00
|
|
|
if (!positiveResult) {
|
|
|
|
// user cancelled; reset checkbox values to their previous state
|
|
|
|
mValues = mPrevValues.clone();
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
mPrevValues = mValues.clone();
|
|
|
|
}
|
|
|
|
|
2013-03-15 03:52:53 -07:00
|
|
|
ThreadUtils.postToBackgroundThread(new Runnable() {
|
2013-02-26 21:48:00 -08:00
|
|
|
@Override
|
2012-06-26 23:15:23 -07:00
|
|
|
public void run() {
|
|
|
|
for (int i = 0; i < mEntryKeys.length; i++) {
|
|
|
|
String key = mEntryKeys[i].toString();
|
|
|
|
persistBoolean(key, mValues[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
protected boolean persistBoolean(String key, boolean value) {
|
|
|
|
if (isPersistent()) {
|
|
|
|
if (value == getPersistedBoolean(!value)) {
|
|
|
|
// It's already there, so the same as persisting
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
PreferenceManager.getDefaultSharedPreferences(getContext())
|
|
|
|
.edit().putBoolean(key, value).commit();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected boolean getPersistedBoolean(String key, boolean defaultReturnValue) {
|
|
|
|
if (!isPersistent())
|
|
|
|
return defaultReturnValue;
|
|
|
|
|
|
|
|
return PreferenceManager.getDefaultSharedPreferences(getContext())
|
|
|
|
.getBoolean(key, defaultReturnValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
private void loadPersistedValues() {
|
|
|
|
if (mEntryKeys == null || mInitialValues == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
final int entryCount = mEntryKeys.length;
|
|
|
|
if (entryCount != mEntries.length || entryCount != mInitialValues.length) {
|
|
|
|
throw new IllegalStateException(
|
|
|
|
"MultiChoicePreference entryKeys and initialValues arrays must be the same length");
|
|
|
|
}
|
|
|
|
|
|
|
|
mValues = new boolean[entryCount];
|
2013-03-15 03:52:53 -07:00
|
|
|
ThreadUtils.postToBackgroundThread(new Runnable() {
|
2013-02-26 21:48:00 -08:00
|
|
|
@Override
|
2012-06-26 23:15:23 -07:00
|
|
|
public void run() {
|
|
|
|
for (int i = 0; i < entryCount; i++) {
|
|
|
|
String key = mEntryKeys[i].toString();
|
|
|
|
boolean initialValue = mInitialValues[i].equals("true");
|
|
|
|
mValues[i] = getPersistedBoolean(key, initialValue);
|
|
|
|
}
|
|
|
|
mPrevValues = mValues.clone();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|