|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 package org.mozilla.gecko.preferences; |
|
6 |
|
7 import org.mozilla.gecko.R; |
|
8 |
|
9 import android.app.AlertDialog; |
|
10 import android.content.Context; |
|
11 import android.content.DialogInterface; |
|
12 import android.content.res.Resources; |
|
13 import android.preference.Preference; |
|
14 import android.view.View; |
|
15 import android.widget.TextView; |
|
16 |
|
17 /** |
|
18 * Represents an element in a <code>CustomListCategory</code> preference menu. |
|
19 * This preference con display a dialog when clicked, and also supports |
|
20 * being set as a default item within the preference list category. |
|
21 */ |
|
22 |
|
23 public abstract class CustomListPreference extends Preference implements View.OnLongClickListener { |
|
24 protected String LOGTAG = "CustomListPreference"; |
|
25 |
|
26 // Indices of the buttons of the Dialog. |
|
27 public static final int INDEX_SET_DEFAULT_BUTTON = 0; |
|
28 |
|
29 // Dialog item labels. |
|
30 private String[] mDialogItems; |
|
31 |
|
32 // Dialog displayed when this element is tapped. |
|
33 protected AlertDialog mDialog; |
|
34 |
|
35 // Cache label to avoid repeated use of the resource system. |
|
36 protected final String LABEL_IS_DEFAULT; |
|
37 protected final String LABEL_SET_AS_DEFAULT; |
|
38 protected final String LABEL_REMOVE; |
|
39 |
|
40 protected boolean mIsDefault; |
|
41 |
|
42 // Enclosing parent category that contains this preference. |
|
43 protected final CustomListCategory mParentCategory; |
|
44 |
|
45 /** |
|
46 * Create a preference object to represent a list preference that is attached to |
|
47 * a category. |
|
48 * |
|
49 * @param context The activity context we operate under. |
|
50 * @param parentCategory The PreferenceCategory this object exists within. |
|
51 */ |
|
52 public CustomListPreference(Context context, CustomListCategory parentCategory) { |
|
53 super(context); |
|
54 |
|
55 mParentCategory = parentCategory; |
|
56 setLayoutResource(getPreferenceLayoutResource()); |
|
57 |
|
58 setOnPreferenceClickListener(new OnPreferenceClickListener() { |
|
59 @Override |
|
60 public boolean onPreferenceClick(Preference preference) { |
|
61 CustomListPreference sPref = (CustomListPreference) preference; |
|
62 sPref.showDialog(); |
|
63 return true; |
|
64 } |
|
65 }); |
|
66 |
|
67 Resources res = getContext().getResources(); |
|
68 |
|
69 // Fetch these strings now, instead of every time we ever want to relabel a button. |
|
70 LABEL_IS_DEFAULT = res.getString(R.string.pref_default); |
|
71 LABEL_SET_AS_DEFAULT = res.getString(R.string.pref_dialog_set_default); |
|
72 LABEL_REMOVE = res.getString(R.string.pref_dialog_remove); |
|
73 } |
|
74 |
|
75 /** |
|
76 * Returns the Android resource id for the layout. |
|
77 */ |
|
78 protected abstract int getPreferenceLayoutResource(); |
|
79 |
|
80 /** |
|
81 * Set whether this object's UI should display this as the default item. |
|
82 * Note: This must be called from the UI thread because it touches the view hierarchy. |
|
83 * |
|
84 * To ensure proper ordering, this method should only be called after this Preference |
|
85 * is added to the PreferenceCategory. |
|
86 * |
|
87 * @param isDefault Flag indicating if this represents the default list item. |
|
88 */ |
|
89 public void setIsDefault(boolean isDefault) { |
|
90 mIsDefault = isDefault; |
|
91 if (isDefault) { |
|
92 setOrder(0); |
|
93 setSummary(LABEL_IS_DEFAULT); |
|
94 } else { |
|
95 setOrder(1); |
|
96 setSummary(""); |
|
97 } |
|
98 } |
|
99 |
|
100 private String[] getCachedDialogItems() { |
|
101 if (mDialogItems == null) { |
|
102 mDialogItems = createDialogItems(); |
|
103 } |
|
104 return mDialogItems; |
|
105 } |
|
106 |
|
107 /** |
|
108 * Returns the strings to be displayed in the dialog. |
|
109 */ |
|
110 abstract protected String[] createDialogItems(); |
|
111 |
|
112 /** |
|
113 * Display a dialog for this preference, when the preference is clicked. |
|
114 */ |
|
115 public void showDialog() { |
|
116 final AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); |
|
117 builder.setTitle(getTitle().toString()); |
|
118 builder.setItems(getCachedDialogItems(), new DialogInterface.OnClickListener() { |
|
119 // Forward relevant events to the container class for handling. |
|
120 @Override |
|
121 public void onClick(DialogInterface dialog, int indexClicked) { |
|
122 hideDialog(); |
|
123 onDialogIndexClicked(indexClicked); |
|
124 } |
|
125 }); |
|
126 |
|
127 configureDialogBuilder(builder); |
|
128 |
|
129 // We have to construct the dialog itself on the UI thread. |
|
130 mDialog = builder.create(); |
|
131 mDialog.setOnShowListener(new DialogInterface.OnShowListener() { |
|
132 // Called when the dialog is shown (so we're finally able to manipulate button enabledness). |
|
133 @Override |
|
134 public void onShow(DialogInterface dialog) { |
|
135 configureShownDialog(); |
|
136 } |
|
137 }); |
|
138 mDialog.show(); |
|
139 } |
|
140 |
|
141 /** |
|
142 * (Optional) Configure the AlertDialog builder. |
|
143 */ |
|
144 protected void configureDialogBuilder(AlertDialog.Builder builder) { |
|
145 return; |
|
146 } |
|
147 |
|
148 abstract protected void onDialogIndexClicked(int index); |
|
149 |
|
150 /** |
|
151 * Disables buttons in the shown AlertDialog as required. The button elements are not created |
|
152 * until after show is called, so this method has to be called from the onShowListener above. |
|
153 * @see this.showDialog |
|
154 */ |
|
155 protected void configureShownDialog() { |
|
156 // If this is already the default list item, disable the button for setting this as the default. |
|
157 final TextView defaultButton = (TextView) mDialog.getListView().getChildAt(INDEX_SET_DEFAULT_BUTTON); |
|
158 if (mIsDefault) { |
|
159 defaultButton.setEnabled(false); |
|
160 |
|
161 // Failure to unregister this listener leads to tapping the button dismissing the dialog |
|
162 // without doing anything. |
|
163 defaultButton.setOnClickListener(null); |
|
164 } |
|
165 } |
|
166 |
|
167 /** |
|
168 * Hide the dialog we previously created, if any. |
|
169 */ |
|
170 public void hideDialog() { |
|
171 if (mDialog != null && mDialog.isShowing()) { |
|
172 mDialog.dismiss(); |
|
173 } |
|
174 } |
|
175 |
|
176 @Override |
|
177 public boolean onLongClick(View view) { |
|
178 // Show the preference dialog on long-press. |
|
179 showDialog(); |
|
180 return true; |
|
181 } |
|
182 } |