gecko/mobile/android/base/preferences/CustomListPreference.java

183 lines
6.1 KiB
Java

/* 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 android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.preference.Preference;
import android.view.View;
import android.widget.TextView;
/**
* Represents an element in a <code>CustomListCategory</code> preference menu.
* This preference con display a dialog when clicked, and also supports
* being set as a default item within the preference list category.
*/
public abstract class CustomListPreference extends Preference implements View.OnLongClickListener {
protected String LOGTAG = "CustomListPreference";
// Indices of the buttons of the Dialog.
public static final int INDEX_SET_DEFAULT_BUTTON = 0;
// Dialog item labels.
private String[] mDialogItems;
// Dialog displayed when this element is tapped.
protected AlertDialog mDialog;
// Cache label to avoid repeated use of the resource system.
protected final String LABEL_IS_DEFAULT;
protected final String LABEL_SET_AS_DEFAULT;
protected final String LABEL_REMOVE;
protected boolean mIsDefault;
// Enclosing parent category that contains this preference.
protected final CustomListCategory mParentCategory;
/**
* Create a preference object to represent a list preference that is attached to
* a category.
*
* @param context The activity context we operate under.
* @param parentCategory The PreferenceCategory this object exists within.
*/
public CustomListPreference(Context context, CustomListCategory parentCategory) {
super(context);
mParentCategory = parentCategory;
setLayoutResource(getPreferenceLayoutResource());
setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
CustomListPreference sPref = (CustomListPreference) preference;
sPref.showDialog();
return true;
}
});
Resources res = getContext().getResources();
// Fetch these strings now, instead of every time we ever want to relabel a button.
LABEL_IS_DEFAULT = res.getString(R.string.pref_default);
LABEL_SET_AS_DEFAULT = res.getString(R.string.pref_dialog_set_default);
LABEL_REMOVE = res.getString(R.string.pref_dialog_remove);
}
/**
* Returns the Android resource id for the layout.
*/
protected abstract int getPreferenceLayoutResource();
/**
* Set whether this object's UI should display this as the default item.
* Note: This must be called from the UI thread because it touches the view hierarchy.
*
* To ensure proper ordering, this method should only be called after this Preference
* is added to the PreferenceCategory.
*
* @param isDefault Flag indicating if this represents the default list item.
*/
public void setIsDefault(boolean isDefault) {
mIsDefault = isDefault;
if (isDefault) {
setOrder(0);
setSummary(LABEL_IS_DEFAULT);
} else {
setOrder(1);
setSummary("");
}
}
private String[] getCachedDialogItems() {
if (mDialogItems == null) {
mDialogItems = createDialogItems();
}
return mDialogItems;
}
/**
* Returns the strings to be displayed in the dialog.
*/
abstract protected String[] createDialogItems();
/**
* Display a dialog for this preference, when the preference is clicked.
*/
public void showDialog() {
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(getTitle().toString());
builder.setItems(getCachedDialogItems(), new DialogInterface.OnClickListener() {
// Forward relevant events to the container class for handling.
@Override
public void onClick(DialogInterface dialog, int indexClicked) {
hideDialog();
onDialogIndexClicked(indexClicked);
}
});
configureDialogBuilder(builder);
// We have to construct the dialog itself on the UI thread.
mDialog = builder.create();
mDialog.setOnShowListener(new DialogInterface.OnShowListener() {
// Called when the dialog is shown (so we're finally able to manipulate button enabledness).
@Override
public void onShow(DialogInterface dialog) {
configureShownDialog();
}
});
mDialog.show();
}
/**
* (Optional) Configure the AlertDialog builder.
*/
protected void configureDialogBuilder(AlertDialog.Builder builder) {
return;
}
abstract protected void onDialogIndexClicked(int index);
/**
* Disables buttons in the shown AlertDialog as required. The button elements are not created
* until after show is called, so this method has to be called from the onShowListener above.
* @see this.showDialog
*/
protected void configureShownDialog() {
// If this is already the default list item, disable the button for setting this as the default.
final TextView defaultButton = (TextView) mDialog.getListView().getChildAt(INDEX_SET_DEFAULT_BUTTON);
if (mIsDefault) {
defaultButton.setEnabled(false);
// Failure to unregister this listener leads to tapping the button dismissing the dialog
// without doing anything.
defaultButton.setOnClickListener(null);
}
}
/**
* Hide the dialog we previously created, if any.
*/
public void hideDialog() {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
}
}
@Override
public boolean onLongClick(View view) {
// Show the preference dialog on long-press.
showDialog();
return true;
}
}