package org.commcare.views.widgets; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.util.TypedValue; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.TextView; import org.commcare.dalvik.R; import org.commcare.utils.StringUtils; import org.javarosa.core.model.SelectChoice; import org.javarosa.core.model.data.IAnswerData; import org.javarosa.core.model.data.SelectMultiData; import org.javarosa.core.model.data.helper.Selection; import org.javarosa.form.api.FormEntryPrompt; import java.util.Vector; /** * SpinnerMultiWidget, like SelectMultiWidget handles multiple selection fields using checkboxes, * but the user clicks a button to see the checkboxes. The goal is to be more compact. If images, * audio, or video are specified in the select answers they are ignored. WARNING: There is a bug in * android versions previous to 2.0 that affects this widget. You can find the report here: * http://code.google.com/p/android/issues/detail?id=922 This bug causes text to be white in alert * boxes, which makes the select options invisible in this widget. For this reason, this widget * should not be used on phones with android versions lower than 2.0. * * @author Jeff Beorse (jeff@beorse.net) */ public class SpinnerMultiWidget extends QuestionWidget { private final Vector<SelectChoice> mItems; // The possible select answers private final CharSequence[] answerItems; // The button to push to display the answers to choose from private final Button button; // Defines which answers are selected private final boolean[] selections; // The alert box that contains the answer selection view private final AlertDialog.Builder alert_builder; // Displays the current selections below the button private final TextView selectionText; @SuppressWarnings("unchecked") public SpinnerMultiWidget(final Context context, FormEntryPrompt prompt) { super(context, prompt); mItems = mPrompt.getSelectChoices(); selections = new boolean[mItems.size()]; answerItems = new CharSequence[mItems.size()]; alert_builder = new AlertDialog.Builder(context); button = new Button(context); selectionText = new TextView(getContext()); // Build View for (int i = 0; i < mItems.size(); i++) { answerItems[i] = mPrompt.getSelectChoiceText(mItems.get(i)); } selectionText.setText(StringUtils.getStringSpannableRobust(context, R.string.selected)); selectionText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, mQuestionFontSize); selectionText.setVisibility(View.GONE); button.setText(StringUtils.getStringSpannableRobust(context, R.string.select_answer)); button.setTextSize(TypedValue.COMPLEX_UNIT_DIP, mQuestionFontSize); button.setPadding(0, 0, 0, 7); // Give the button a click listener. This defines the alert as well. All the // click and selection behavior is defined here. button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { alert_builder.setTitle(mPrompt.getQuestionText()).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { boolean first = true; selectionText.setText(""); for (int i = 0; i < selections.length; i++) { if (selections[i]) { if (first) { first = false; selectionText.setText(StringUtils.getStringSpannableRobust(context, R.string.selected) + answerItems[i].toString()); selectionText.setVisibility(View.VISIBLE); } else { selectionText.setText(selectionText.getText() + ", " + answerItems[i].toString()); } } } widgetEntryChanged(); } }); alert_builder.setMultiChoiceItems(answerItems, selections, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { selections[which] = isChecked; widgetEntryChanged(); } }); AlertDialog alert = alert_builder.create(); alert.show(); widgetEntryChanged(); } }); // Fill in previous answers Vector<Selection> ve = new Vector<>(); if (mPrompt.getAnswerValue() != null) { ve = (Vector<Selection>)mPrompt.getAnswerValue().getValue(); } if (ve != null) { boolean first = true; for (int i = 0; i < selections.length; ++i) { String value = mPrompt.getSelectChoices().get(i).getValue(); boolean found = false; for (Selection s : ve) { if (value.equals(s.getValue())) { found = true; break; } } selections[i] = found; if (found) { if (first) { first = false; selectionText.setText(StringUtils.getStringSpannableRobust(context, R.string.selected) + answerItems[i].toString()); selectionText.setVisibility(View.VISIBLE); } else { selectionText.setText(selectionText.getText() + ", " + answerItems[i].toString()); } } } } addView(button); addView(selectionText); } @Override public IAnswerData getAnswer() { Vector<Selection> vc = new Vector<>(); for (int i = 0; i < mItems.size(); i++) { if (selections[i]) { SelectChoice sc = mItems.get(i); vc.add(new Selection(sc)); } } if (vc.size() == 0) { return null; } else { return new SelectMultiData(vc); } } @Override public void clearAnswer() { selectionText.setText(R.string.selected); selectionText.setVisibility(View.GONE); for (int i = 0; i < selections.length; i++) { selections[i] = false; } } @Override public void setFocus(Context context) { // Hide the soft keyboard if it's showing. InputMethodManager inputManager = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.hideSoftInputFromWindow(this.getWindowToken(), 0); } @Override public void setOnLongClickListener(OnLongClickListener l) { button.setOnLongClickListener(l); } @Override public void unsetListeners() { super.unsetListeners(); button.setOnLongClickListener(null); } @Override public void cancelLongPress() { super.cancelLongPress(); button.cancelLongPress(); } }