package org.commcare.views;
import android.content.Context;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AutoCompleteTextView;
import org.commcare.adapters.ComboboxAdapter;
import java.util.Vector;
/**
* Custom view that builds upon Android's built-in AutoCompleteTextView and adds:
* -Validation and auto-correcting of user-entered text to only allow strings that are part of
* an available answer choice
* -The ability to set an adapter that implements custom filtering rules (rather than using
* the default filter of AutoCompleteTextView)
*
* @author Aliza Stone
*/
public class Combobox extends AutoCompleteTextView {
private Vector<String> 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) {
super(context);
this.customAdapter = adapter;
setAdapter(adapter);
setupChoices(choices);
setThreshold(1);
setListeners();
setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}
private void setupChoices(Vector<String> choices) {
this.choices = choices;
this.choicesAllLowerCase = new Vector<>();
for (String s : this.choices) {
choicesAllLowerCase.add(s.toLowerCase());
}
}
private void setListeners() {
if (customAdapter.shouldRestrictTyping()) {
addTextChangedListener(getWhileTypingValidator());
}
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showDropDown();
}
});
setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
showDropDown();
} else {
autoCorrectCapitalization();
}
}
});
}
private TextWatcher getWhileTypingValidator() {
return new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (!fixingInvalidEntry) {
lastValidCursorLocation = getSelectionStart();
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
fixingInvalidEntry = false;
if (!customAdapter.isValidUserEntry(s.toString())) {
fixingInvalidEntry = true;
// Re-set the entered text to be what it was before this change was made
setText(lastAcceptableStringEntered);
// Put the cursor back where it was
setSelection(lastValidCursorLocation);
} else {
lastAcceptableStringEntered = s.toString();
}
}
};
}
/**
* If the user has entered a valid answer but with different case, change the case for them
*/
public void autoCorrectCapitalization() {
String enteredText = getText().toString();
if (enteredText != null && !choices.contains(enteredText) &&
choicesAllLowerCase.contains(enteredText.toLowerCase())) {
int index = choicesAllLowerCase.indexOf(enteredText.toLowerCase());
setText(choices.get(index));
}
}
}