Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions app/src/org/commcare/adapters/ComboboxAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
import android.widget.TextView;

import org.commcare.dalvik.R;
import org.javarosa.core.model.ComboItem;
import org.javarosa.core.model.ComboboxFilterRule;
import org.javarosa.core.model.FuzzyMatchFilterRule;
import org.javarosa.core.model.MultiWordFilterRule;
import org.javarosa.core.model.StandardFilterRule;

import java.util.ArrayList;

Expand All @@ -23,14 +21,14 @@
*
* @author Aliza Stone
*/
public class ComboboxAdapter extends ArrayAdapter<String> {
public class ComboboxAdapter extends ArrayAdapter<ComboItem> {

private float customTextSize;
protected final String[] allChoices;
protected String[] currentChoices;
protected final ComboItem[] allChoices;
protected ComboItem[] currentChoices;
protected ComboboxFilterRule filterRule;

public ComboboxAdapter(final Context context, final String[] objects,
public ComboboxAdapter(final Context context, final ComboItem[] objects,
ComboboxFilterRule filterRule) {
super(context, R.layout.custom_spinner_item, objects);
allChoices = currentChoices = objects;
Expand All @@ -44,7 +42,7 @@ public ComboboxAdapter(final Context context, final String[] objects,
* there being at least 1 answer option in the dropdown list when this string is entered.
*/
public boolean isValidUserEntry(String enteredText) {
for (String choice : allChoices) {
for (ComboItem choice : allChoices) {
if (filterRule.choiceShouldBeShown(choice, enteredText)) {
return true;
}
Expand Down Expand Up @@ -77,7 +75,7 @@ public int getCount() {
}

@Override
public String getItem(int position) {
public ComboItem getItem(int position) {
return currentChoices[position];
}

Expand All @@ -86,22 +84,22 @@ public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<String> matched = new ArrayList<>();
for (String choice : allChoices) {
ArrayList<ComboItem> matched = new ArrayList<>();
for (ComboItem choice : allChoices) {
if (constraint == null || filterRule.choiceShouldBeShown(choice, constraint)) {
matched.add(choice);
}
}

FilterResults results = new FilterResults();
results.values = matched.toArray(new String[]{});
results.values = matched.toArray(new ComboItem[]{});
results.count = matched.size();
return results;
}

@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
currentChoices = (String[]) results.values;
currentChoices = (ComboItem[]) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
Expand Down
13 changes: 7 additions & 6 deletions app/src/org/commcare/views/Combobox.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.text.TextWatcher;

import org.commcare.adapters.ComboboxAdapter;
import org.javarosa.core.model.ComboItem;

import java.util.Vector;

Expand All @@ -22,14 +23,14 @@
*/
public class Combobox extends AppCompatAutoCompleteTextView {

private Vector<String> choices;
private Vector<ComboItem> choices;
private Vector<String> choicesAllLowerCase;
private CharSequence lastAcceptableStringEntered = "";
private int lastValidCursorLocation;
private boolean fixingInvalidEntry;
private ComboboxAdapter customAdapter;

public Combobox(Context context, Vector<String> choices, ComboboxAdapter adapter) {
public Combobox(Context context, Vector<ComboItem> choices, ComboboxAdapter adapter) {
super(context);
this.customAdapter = adapter;

Expand All @@ -40,11 +41,11 @@ public Combobox(Context context, Vector<String> choices, ComboboxAdapter adapter
setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}

private void setupChoices(Vector<String> choices) {
private void setupChoices(Vector<ComboItem> choices) {
this.choices = choices;
this.choicesAllLowerCase = new Vector<>();
for (String s : this.choices) {
choicesAllLowerCase.add(s.toLowerCase());
for (ComboItem s : this.choices) {
choicesAllLowerCase.add(s.getDisplayText().toLowerCase());
}
}

Expand Down Expand Up @@ -101,7 +102,7 @@ public void autoCorrectCapitalization() {
if (enteredText != null && !choices.contains(enteredText) &&
choicesAllLowerCase.contains(enteredText.toLowerCase())) {
int index = choicesAllLowerCase.indexOf(enteredText.toLowerCase());
setText(choices.get(index));
setText(choices.get(index).getDisplayText());
}
}

Expand Down
76 changes: 59 additions & 17 deletions app/src/org/commcare/views/widgets/ComboboxWidget.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import org.commcare.adapters.ComboboxAdapter;
import org.commcare.views.Combobox;
import org.javarosa.core.model.ComboItem;
import org.javarosa.core.model.ComboboxFilterRule;
import org.javarosa.core.model.SelectChoice;
import org.javarosa.core.model.data.IAnswerData;
Expand All @@ -27,14 +28,15 @@
public class ComboboxWidget extends QuestionWidget {

private Vector<SelectChoice> choices;
private Vector<String> choiceTexts;
private Vector<ComboItem> choiceComboItems;
private Combobox comboBox;
private boolean wasWidgetChangedOnTextChanged = false;
private ComboItem selectedComboItem = null;

public ComboboxWidget(Context context, FormEntryPrompt prompt, ComboboxFilterRule filterRule) {
super(context, prompt);
initChoices(prompt);
comboBox = setUpComboboxForWidget(context, choiceTexts, filterRule, mQuestionFontSize);
comboBox = setUpComboboxForWidget(context, choiceComboItems, filterRule, mQuestionFontSize);
addView(comboBox);

comboBox.setEnabled(!prompt.isReadOnly());
Expand All @@ -43,35 +45,45 @@ public ComboboxWidget(Context context, FormEntryPrompt prompt, ComboboxFilterRul
fillInPreviousAnswer(prompt);
}

private static Combobox setUpComboboxForWidget(Context context, Vector<String> choices,
private static Combobox setUpComboboxForWidget(Context context, Vector<ComboItem> choices,
ComboboxFilterRule filterRule, int fontSize) {
ComboboxAdapter adapter =
getAdapterForComboboxWidget(context, choices.toArray(new String[]{}),
getAdapterForComboboxWidget(context, choices.toArray(new ComboItem[]{}),
filterRule, fontSize);
Combobox combobox = new Combobox(context, choices, adapter);
combobox.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSize);
return combobox;
}

private static ComboboxAdapter getAdapterForComboboxWidget(Context context, String[] choices,
private static ComboboxAdapter getAdapterForComboboxWidget(Context context, ComboItem[] choices,
ComboboxFilterRule filterRule,
int fontSize) {
choices = SpinnerWidget.getChoicesWithEmptyFirstSlot(choices);
choices = getComboItemChoicesWithEmptyFirstSlot(choices);
ComboboxAdapter adapter = new ComboboxAdapter(context, choices, filterRule);
adapter.setCustomTextSize(fontSize);
return adapter;
}

public static ComboItem[] getComboItemChoicesWithEmptyFirstSlot(ComboItem[] originalChoices) {
ComboItem[] newChoicesList = new ComboItem[originalChoices.length+1];
newChoicesList[0] = new ComboItem("", "", -1);
System.arraycopy(originalChoices, 0, newChoicesList, 1, originalChoices.length);
return newChoicesList;
}

private void initChoices(FormEntryPrompt prompt) {
choices = getSelectChoices();
choiceTexts = new Vector<>();
choiceComboItems = new Vector<>();
for (int i = 0; i < choices.size(); i++) {
choiceTexts.add(prompt.getSelectChoiceText(choices.get(i)));
choiceComboItems.add(new ComboItem(prompt.getSelectChoiceText(choices.get(i)),choices.get(i).getValue(),choices.get(i).getIndex()));
}
}

private void addListeners() {
comboBox.setOnItemClickListener((parent, view, position, id) -> widgetEntryChanged());
comboBox.setOnItemClickListener((parent, view, position, id) -> {
selectedComboItem = (ComboItem) parent.getItemAtPosition(position);
widgetEntryChanged();}
);

// Note that Combobox has an OnFocusChangeListener defined in its own class, so when
// re-setting it here we have to make sure to do all of the same things that the original
Expand Down Expand Up @@ -109,15 +121,24 @@ public void afterTextChanged(Editable s) {
private void fillInPreviousAnswer(FormEntryPrompt prompt) {
if (prompt.getAnswerValue() != null) {
String previousAnswerValue = ((Selection)prompt.getAnswerValue().getValue()).getValue();
for (int i = 0; i < choices.size(); i++) {
if (choices.get(i).getValue().equals(previousAnswerValue)) {
comboBox.setText(choiceTexts.get(i));
break;
if (previousAnswerValue != null) {
selectedComboItem = getComboItemFromSelectionValue(previousAnswerValue);
if (selectedComboItem != null) {
comboBox.setText(selectedComboItem.getDisplayText());
}
}
}
}

private ComboItem getComboItemFromSelectionValue(String selectionValue) {
for (ComboItem comboItem: choiceComboItems) {
if (comboItem.getValue().equals(selectionValue)) {
return comboItem;
}
}
return null;
}

@Override
public IAnswerData getAnswer() {
// So that we can see any error message that gets shown as a result of this
Expand All @@ -127,20 +148,41 @@ public IAnswerData getAnswer() {

comboBox.autoCorrectCapitalization();
String enteredText = comboBox.getText().toString();
if (choiceTexts.contains(enteredText)) {
int i = choiceTexts.indexOf(enteredText);
return new SelectOneData(new Selection(choices.elementAt(i)));
} else if ("".equals(enteredText)) {
if (selectedComboItem != null && selectedComboItem.getDisplayText().equals(enteredText) &&
choiceComboItems.contains(selectedComboItem)) {
int selectChoiceIndex = selectedComboItem.getSelectChoiceIndex();
return new SelectOneData(new Selection(choices.elementAt(selectChoiceIndex)));
} else if (selectedComboItem == null && !"".equals(enteredText)) {
// User may have typed in text that matches one of the choices, even if they didn't
// explicitly select it from the dropdown
ComboItem matchingItem = getComboItemFromDisplayText(enteredText);
if (matchingItem != null) {
int selectChoiceIndex = matchingItem.getSelectChoiceIndex();
return new SelectOneData(new Selection(choices.elementAt(selectChoiceIndex)));
}
}
selectedComboItem = null;
if ("".equals(enteredText)) {
return null;
} else {
return new InvalidData("The text entered is not a valid answer choice",
new SelectOneData(new Selection(enteredText)));
}
}

private ComboItem getComboItemFromDisplayText(String displayText) {
for (ComboItem comboItem: choiceComboItems) {
if (comboItem.getDisplayText().equals(displayText)) {
return comboItem;
}
}
return null;
}

@Override
public void clearAnswer() {
comboBox.setText("");
selectedComboItem = null;
}

@Override
Expand Down