Bug 974286 - Remove mSelected from PromptListAdapter. r=bnicholson

This commit is contained in:
Wes Johnston 2014-02-25 08:55:14 -08:00
parent ac63b04c1c
commit 43f4c2789b
6 changed files with 98 additions and 88 deletions

View File

@ -92,6 +92,7 @@ import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.animation.Interpolator;
import android.widget.RelativeLayout;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.ViewFlipper;
@ -2424,7 +2425,7 @@ abstract public class BrowserApp extends GeckoApp
msgString = R.string.exit_guest_session_text;
}
ps.show(res.getString(titleString), res.getString(msgString), null, false);
ps.show(res.getString(titleString), res.getString(msgString), null, ListView.CHOICE_MODE_NONE);
}
public void subscribeToFeeds(Tab tab) {

View File

@ -36,6 +36,8 @@ import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import java.util.ArrayList;
public class Prompt implements OnClickListener, OnCancelListener, OnItemClickListener {
private static final String LOGTAG = "GeckoPromptService";
@ -47,6 +49,7 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
private final Context mContext;
private PromptCallback mCallback;
private String mGuid;
private PromptListAdapter mAdapter;
private static boolean mInitialized = false;
private static int mGroupPaddingSize;
@ -56,7 +59,6 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
private static int mIconSize;
private static int mInputPaddingSize;
private static int mMinRowSize;
private PromptListAdapter mAdapter;
public Prompt(Context context, PromptCallback callback) {
this(context);
@ -84,7 +86,7 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
// Don't add padding to color picker views
if (input.canApplyInputStyle()) {
view.setPadding(mInputPaddingSize, 0, mInputPaddingSize, 0);
}
}
return view;
}
@ -93,11 +95,7 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
}
public void show(String title, String text, PromptListItem[] listItems, boolean multipleSelection) {
show(title, text, listItems, multipleSelection, null);
}
public void show(String title, String text, PromptListItem[] listItems, boolean multipleSelection, boolean[] selected) {
public void show(String title, String text, PromptListItem[] listItems, int choiceMode) {
ThreadUtils.assertOnUiThread();
GeckoAppShell.getLayerView().abortPanning();
@ -114,7 +112,7 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
// 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, selected);
addListItems(builder, listItems, choiceMode);
} else if (!addInputs(builder)) {
// If we failed to add any requested input elements, don't show the dialog
return;
@ -151,23 +149,25 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
*/
private void addListResult(final JSONObject result, int which) {
try {
boolean[] selectedItems = mAdapter.getSelected();
if (selectedItems != null) {
JSONArray selected = new JSONArray();
for (int i = 0; i < selectedItems.length; i++) {
if (selectedItems[i]) {
selected.put(i);
}
JSONArray selected = new JSONArray();
// If the button has already been filled in
ArrayList<Integer> selectedItems = mAdapter.getSelected();
for (Integer item : selectedItems) {
selected.put(item);
}
// If we haven't assigned a button yet, or we assigned it to -1, assign the which
// parameter to both selected and the button.
if (!result.has("button") || result.optInt("button") == -1) {
if (!selectedItems.contains(which)) {
selected.put(which);
}
result.put("list", selected);
} else {
// Mirror the selected array from multi choice for consistency.
JSONArray selected = new JSONArray();
selected.put(which);
result.put("list", selected);
// Make the button be the index of the select item.
result.put("button", which);
}
result.put("list", selected);
} catch(JSONException ex) { }
}
@ -205,11 +205,10 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
ThreadUtils.assertOnUiThread();
JSONObject ret = new JSONObject();
try {
ListView list = mDialog.getListView();
addButtonResult(ret, which);
addInputValues(ret);
if (list != null || mAdapter.getSelected() != null) {
if (mAdapter != null) {
addListResult(ret, which);
}
} catch(Exception ex) {
@ -224,28 +223,27 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
}
/* 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 mAdapter.selected is set in the prompt before addListItems is called, the items will be
* shown with "checkmarks" on their left side.
* or multiple selection lists.
*
* @param builder
* The alert builder currently building this dialog.
* @param listItems
* The items to add.
* @param multipleSelection
* If true, and mAdapter.getSelected is defined to be a non-zero-length list, the list will show checkmarks on the
* left and allow multiple selection.
* @param selected
* A boolean array indicating whether a rows is selected or not. If this is a single select list, only the first true element will be used.
* @param choiceMode
* One of the ListView.CHOICE_MODE constants to designate whether this list shows checkmarks, radios buttons, or nothing.
*/
private void addListItems(AlertDialog.Builder builder, PromptListItem[] listItems, boolean multipleSelection, boolean[] selected) {
if (selected != null && selected.length > 0) {
if (multipleSelection) {
addMultiSelectList(builder, listItems, selected);
} else {
addSingleSelectList(builder, listItems, selected);
}
} else {
addMenuList(builder, listItems);
private void addListItems(AlertDialog.Builder builder, PromptListItem[] listItems, int choiceMode) {
switch(choiceMode) {
case ListView.CHOICE_MODE_MULTIPLE_MODAL:
case ListView.CHOICE_MODE_MULTIPLE:
addMultiSelectList(builder, listItems);
break;
case ListView.CHOICE_MODE_SINGLE:
addSingleSelectList(builder, listItems);
break;
case ListView.CHOICE_MODE_NONE:
default:
addMenuList(builder, listItems);
}
}
@ -258,16 +256,13 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
* @param listItems
* The items to add.
*/
private void addMultiSelectList(AlertDialog.Builder builder, PromptListItem[] listItems, boolean[] selected) {
mAdapter = new PromptListAdapter(mContext, R.layout.select_dialog_multichoice, listItems);
mAdapter.setSelected(selected);
private void addMultiSelectList(AlertDialog.Builder builder, PromptListItem[] listItems) {
ListView listView = (ListView) mInflater.inflate(R.layout.select_dialog_list, null);
listView.setOnItemClickListener(this);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setAdapter(mAdapter);
builder.setInverseBackgroundForced(true);
mAdapter = new PromptListAdapter(mContext, R.layout.select_dialog_multichoice, listItems);
listView.setAdapter(mAdapter);
builder.setView(listView);
}
@ -278,18 +273,9 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
* @param listItems
* The items to add.
*/
private void addSingleSelectList(AlertDialog.Builder builder, PromptListItem[] listItems, boolean[] selected) {
private void addSingleSelectList(AlertDialog.Builder builder, PromptListItem[] listItems) {
mAdapter = 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 < selected.length; i++) {
if (selected[i]) {
selectedIndex = i;
break;
}
}
builder.setSingleChoiceItems(mAdapter, selectedIndex, this);
builder.setSingleChoiceItems(mAdapter, mAdapter.getSelectedIndex(), this);
}
/* Shows a single-select list.
@ -304,7 +290,6 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
builder.setAdapter(mAdapter, this);
}
/* Wraps an input in a linearlayout. We do this so that we can set padding that appears outside the background
* drawable for the view.
*/
@ -342,13 +327,11 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
} else if (length > 1) {
LinearLayout linearLayout = new LinearLayout(mContext);
linearLayout.setOrientation(LinearLayout.VERTICAL);
for (int i = 0; i < length; i++) {
View content = wrapInput(mInputs[i]);
linearLayout.addView(content);
scrollable |= mInputs[i].getScrollable();
}
root = linearLayout;
}
@ -442,8 +425,16 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
}
PromptListItem[] menuitems = PromptListItem.getArray(geckoObject.optJSONArray("listitems"));
boolean multiple = geckoObject.optBoolean("multiple");
show(title, text, menuitems, multiple, getBooleanArray(geckoObject, "selected"));
String selected = geckoObject.optString("choiceMode");
int choiceMode = ListView.CHOICE_MODE_NONE;
if ("single".equals(selected)) {
choiceMode = ListView.CHOICE_MODE_SINGLE;
} else if ("multiple".equals(selected)) {
choiceMode = ListView.CHOICE_MODE_MULTIPLE;
}
show(title, text, menuitems, choiceMode);
}
private static JSONArray getSafeArray(JSONObject json, String key) {

View File

@ -20,6 +20,8 @@ import android.widget.CheckedTextView;
import android.widget.TextView;
import android.widget.ListView;
import java.util.ArrayList;
public class PromptListAdapter extends ArrayAdapter<PromptListItem> {
private static final int VIEW_TYPE_ITEM = 0;
private static final int VIEW_TYPE_GROUP = 1;
@ -38,8 +40,6 @@ public class PromptListAdapter extends ArrayAdapter<PromptListItem> {
private static int mIconTextPadding;
private static boolean mInitialized = false;
private boolean[] mSelected;
PromptListAdapter(Context context, int textViewResourceId, PromptListItem[] objects) {
super(context, textViewResourceId, objects);
mResourceId = textViewResourceId;
@ -89,15 +89,8 @@ public class PromptListAdapter extends ArrayAdapter<PromptListItem> {
}
public void toggleSelected(int position) {
mSelected[position] = !mSelected[position];
}
public void setSelected(boolean[] selected) {
mSelected = selected;
}
public boolean[] getSelected() {
return mSelected;
PromptListItem item = getItem(position);
item.selected = !item.selected;
}
private void maybeUpdateIcon(PromptListItem item, TextView t) {
@ -133,14 +126,39 @@ public class PromptListAdapter extends ArrayAdapter<PromptListItem> {
private void maybeUpdateCheckedState(ListView list, int position, PromptListItem item, ViewHolder viewHolder) {
viewHolder.textView.setEnabled(!item.disabled && !item.isGroup);
viewHolder.textView.setClickable(item.isGroup || item.disabled);
if (viewHolder.textView instanceof CheckedTextView) {
// Apparently just using ct.setChecked(true) doesn't work, so this
// is stolen from the android source code as a way to set the checked
// state of these items
list.setItemChecked(position, item.selected);
}
}
if (mSelected == null) {
return;
boolean isSelected(int position){
return getItem(position).selected;
}
ArrayList<Integer> getSelected() {
int length = getCount();
ArrayList<Integer> selected = new ArrayList<Integer>();
for (int i = 0; i< length; i++) {
if (isSelected(i)) {
selected.add(i);
}
}
if (list != null) {
list.setItemChecked(position, mSelected[position]);
return selected;
}
int getSelectedIndex() {
int length = getCount();
for (int i = 0; i< length; i++) {
if (isSelected(i)) {
return i;
}
}
return -1;
}
@Override

View File

@ -16,8 +16,9 @@ public class PromptListItem {
public final boolean inGroup;
public final boolean disabled;
public final int id;
public boolean isParent;
public boolean selected;
public boolean isParent;
public Drawable icon;
PromptListItem(JSONObject aObject) {
@ -27,6 +28,7 @@ public class PromptListItem {
disabled = aObject.optBoolean("disabled");
id = aObject.optInt("id");
isParent = aObject.optBoolean("isParent");
selected = aObject.optBoolean("selected");
}
public PromptListItem(String aLabel) {
@ -35,7 +37,6 @@ public class PromptListItem {
inGroup = false;
disabled = false;
id = 0;
isParent = false;
}
static PromptListItem[] getArray(JSONArray items) {

View File

@ -32,14 +32,14 @@ public class PromptService implements GeckoEventListener {
}
public void show(final String aTitle, final String aText, final PromptListItem[] aMenuList,
final boolean aMultipleSelection, final Prompt.PromptCallback callback) {
final int aChoiceMode, final Prompt.PromptCallback callback) {
// The dialog must be created on the UI thread.
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
Prompt p;
p = new Prompt(mContext, callback);
p.show(aTitle, aText, aMenuList, aMultipleSelection);
p.show(aTitle, aText, aMenuList, aChoiceMode);
}
});
}

View File

@ -179,12 +179,11 @@ Prompt.prototype = {
if (item.disabled)
obj.disabled = true;
if (item.selected || hasSelected || this.msg.multiple) {
if (!this.msg.selected) {
this.msg.selected = new Array(this.msg.listitems.length);
hasSelected = true;
if (item.selected) {
if (!this.msg.choiceMode) {
this.msg.choiceMode = "single";
}
this.msg.selected[this.msg.listitems.length] = item.selected;
obj.selected = item.selected;
}
if (item.header)
@ -207,7 +206,7 @@ Prompt.prototype = {
},
setMultiChoiceItems: function(aItems) {
this.msg.multiple = true;
this.msg.choiceMode = "multiple";
return this._setListItems(aItems);
},