diff --git a/mobile/android/base/prompts/Prompt.java b/mobile/android/base/prompts/Prompt.java index 210dc4ce2c2..90ed8d4b4fc 100644 --- a/mobile/android/base/prompts/Prompt.java +++ b/mobile/android/base/prompts/Prompt.java @@ -35,6 +35,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.inputmethod.InputMethodManager; +import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; @@ -116,89 +117,30 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis processMessage(message); } - public void show(String aTitle, String aText, PromptListItem[] aMenuList, boolean aMultipleSelection) { + public void show(String title, String text, PromptListItem[] listItems, boolean multipleSelection) { ThreadUtils.assertOnUiThread(); GeckoAppShell.getLayerView().abortPanning(); AlertDialog.Builder builder = new AlertDialog.Builder(mContext); - if (!TextUtils.isEmpty(aTitle)) { - builder.setTitle(aTitle); + if (!TextUtils.isEmpty(title)) { + builder.setTitle(title); } - if (!TextUtils.isEmpty(aText)) { - builder.setMessage(aText); + if (!TextUtils.isEmpty(text)) { + builder.setMessage(text); } - int length = mInputs == null ? 0 : mInputs.length; - if (aMenuList != null && aMenuList.length > 0) { - int resourceId = android.R.layout.simple_list_item_1; - if (mSelected != null && mSelected.length > 0) { - if (aMultipleSelection) { - resourceId = R.layout.select_dialog_multichoice; - } else { - resourceId = R.layout.select_dialog_singlechoice; - } - } - PromptListAdapter adapter = new PromptListAdapter(mContext, resourceId, aMenuList); - if (mSelected != null && mSelected.length > 0) { - if (aMultipleSelection) { - adapter.listView = (ListView) mInflater.inflate(R.layout.select_dialog_list, null); - adapter.listView.setOnItemClickListener(this); - builder.setInverseBackgroundForced(true); - adapter.listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - adapter.listView.setAdapter(adapter); - builder.setView(adapter.listView); - } else { - int selectedIndex = -1; - for (int i = 0; i < mSelected.length; i++) { - if (mSelected[i]) { - selectedIndex = i; - break; - } - } - mSelected = null; - builder.setSingleChoiceItems(adapter, selectedIndex, this); - } - } else { - builder.setAdapter(adapter, this); - mSelected = null; - } - } else if (length == 1) { - try { - ScrollView view = new ScrollView(mContext); - view.addView(mInputs[0].getView(mContext)); - builder.setView(applyInputStyle(view)); - } catch(UnsupportedOperationException ex) { - // We cannot display these input widgets with this sdk version, - // do not display any dialog and finish the prompt now. - try { - finishDialog(new JSONObject("{\"button\": -1}")); - } catch(JSONException e) { } - return; - } - } else if (length > 1) { - try { - LinearLayout linearLayout = new LinearLayout(mContext); - linearLayout.setOrientation(LinearLayout.VERTICAL); - for (int i = 0; i < length; i++) { - View content = mInputs[i].getView(mContext); - linearLayout.addView(content); - } - ScrollView view = new ScrollView(mContext); - view.addView(linearLayout); - builder.setView(applyInputStyle(view)); - } catch(UnsupportedOperationException ex) { - // We cannot display these input widgets with this sdk version, - // do not display any dialog and finish the prompt now. - try { - finishDialog(new JSONObject("{\"button\": -1}")); - } catch(JSONException e) { } - return; - } + // Because lists are currently added through the normal Android AlertBuilder interface, they're + // incompatible with also adding additional input elements to a dialog. + if (listItems != null && listItems.length > 0) { + addlistItems(builder, listItems, multipleSelection); + } else if (!addInputs(builder)) { + // If we failed to add any requested input elements, don't show the dialog + return; } - length = mButtons == null ? 0 : mButtons.length; + int length = mButtons == null ? 0 : mButtons.length; if (length > 0) { builder.setPositiveButton(mButtons[0], this); if (length > 1) { @@ -264,6 +206,128 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis finishDialog(ret); } + /* Adds a set of list items to the prompt. This can be used for either context menu type dialogs, checked lists, + * or multiple selection lists. If mSelected is set in the prompt before addlistItems is called, the items will be + * shown with "checkmarks" on their left side. + * + * @param builder + * The alert builder currently building this dialog. + * @param listItems + * The items to add. + * @param multipleSelection + * If true, and mSelected is defined to be a non-zero-length list, the list will show checkmarks on the + * left and allow multiple selection. + */ + private void addlistItems(AlertDialog.Builder builder, PromptListItem[] listItems, boolean multipleSelection) { + if (mSelected != null && mSelected.length > 0) { + if (multipleSelection) { + addMultiSelectList(builder, listItems); + } else { + addSingleSelectList(builder, listItems); + } + } else { + addMenuList(builder, listItems); + } + } + + /* Shows a multi-select list with checkmarks on the side. Android doesn't support using an adapter for + * multi-choice lists by default so instead we insert our own custom list so that we can do fancy things + * to the rows like disabling/indenting them. + * + * @param builder + * The alert builder currently building this dialog. + * @param listItems + * The items to add. + */ + private void addMultiSelectList(AlertDialog.Builder builder, PromptListItem[] listItems) { + PromptListAdapter adapter = new PromptListAdapter(mContext, R.layout.select_dialog_multichoice, listItems); + adapter.listView = (ListView) mInflater.inflate(R.layout.select_dialog_list, null); + adapter.listView.setOnItemClickListener(this); + builder.setInverseBackgroundForced(true); + adapter.listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + adapter.listView.setAdapter(adapter); + builder.setView(adapter.listView); + } + + /* Shows a single-select list with radio boxes on the side. + * + * @param builder + * the alert builder currently building this dialog. + * @param listItems + * The items to add. + */ + private void addSingleSelectList(AlertDialog.Builder builder, PromptListItem[] listItems) { + PromptListAdapter adapter = new PromptListAdapter(mContext, R.layout.select_dialog_singlechoice, listItems); + // For single select, we only maintain a single index of the selected row + int selectedIndex = -1; + for (int i = 0; i < mSelected.length; i++) { + if (mSelected[i]) { + selectedIndex = i; + break; + } + } + mSelected = null; + + builder.setSingleChoiceItems(adapter, selectedIndex, this); + } + + /* Shows a single-select list. + * + * @param builder + * the alert builder currently building this dialog. + * @param listItems + * The items to add. + */ + private void addMenuList(AlertDialog.Builder builder, PromptListItem[] listItems) { + PromptListAdapter adapter = new PromptListAdapter(mContext, android.R.layout.simple_list_item_1, listItems); + builder.setAdapter(adapter, this); + mSelected = null; + } + + /* Add the requested input elements to the dialog. + * + * @param builder + * the alert builder currently building this dialog. + * @return + * returns true if the inputs were added successfully. They may fail + * if the requested input is incompatible with this Android version + */ + private boolean addInputs(AlertDialog.Builder builder) { + int length = mInputs == null ? 0 : mInputs.length; + if (length == 0) { + return true; + } + + try { + if (length == 1) { + ScrollView view = new ScrollView(mContext); + view.addView(mInputs[0].getView(mContext)); + builder.setView(applyInputStyle(view)); + } else if (length > 1) { + LinearLayout linearLayout = new LinearLayout(mContext); + linearLayout.setOrientation(LinearLayout.VERTICAL); + for (int i = 0; i < length; i++) { + View content = mInputs[i].getView(mContext); + linearLayout.addView(content); + } + ScrollView view = new ScrollView(mContext); + view.addView(linearLayout); + builder.setView(applyInputStyle(view)); + } + } catch(Exception ex) { + Log.e(LOGTAG, "Error showing prompt inputs", ex); + // We cannot display these input widgets with this sdk version, + // do not display any dialog and finish the prompt now. + try { + finishDialog(new JSONObject("{\"button\": -1}")); + } catch(JSONException e) { } + + return false; + } + + return true; + } + @Override public void onItemClick(AdapterView parent, View view, int position, long id) { ThreadUtils.assertOnUiThread();