package org.odk.collect.android.views; import org.javarosa.core.model.FormIndex; import org.javarosa.core.model.data.IAnswerData; import org.javarosa.form.api.FormEntryCaption; import org.javarosa.form.api.FormEntryPrompt; import org.odk.collect.android.widgets.IBinaryWidget; import org.odk.collect.android.widgets.QuestionWidget; import org.odk.collect.android.widgets.WidgetFactory; import android.content.Context; import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.View.OnLongClickListener; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; /** * This class is * * @author carlhartung */ public class ODKView extends ScrollView implements OnLongClickListener { // starter random number for view IDs private final static int VIEW_ID = 12345; private final static String t = "CLASSNAME"; private final static int TEXTSIZE = 21; private LinearLayout mView; private LinearLayout.LayoutParams mLayout; private ArrayList<QuestionWidget> widgets; public final static String FIELD_LIST = "field-list"; public ODKView(Context context, FormEntryPrompt questionPrompt, FormEntryCaption[] groups) { this(context, new FormEntryPrompt[] { questionPrompt }, groups); } public ODKView(Context context, FormEntryPrompt[] questionPrompts, FormEntryCaption[] groups) { super(context); widgets = new ArrayList<QuestionWidget>(); mView = new LinearLayout(getContext()); mView.setOrientation(LinearLayout.VERTICAL); mView.setGravity(Gravity.TOP); mView.setPadding(0, 7, 0, 0); mLayout = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); mLayout.setMargins(10, 0, 10, 0); // display which group you are in as well as the question addGroupText(groups); boolean first = true; int id = 0; for (FormEntryPrompt p : questionPrompts) { if (!first) { View divider = new View(getContext()); divider.setBackgroundResource(android.R.drawable.divider_horizontal_bright); divider.setMinimumHeight(3); mView.addView(divider); } else { first = false; } // if question or answer type is not supported, use text widget QuestionWidget qw = WidgetFactory.createWidgetFromPrompt(p, getContext()); qw.setLongClickable(true); qw.setOnLongClickListener(this); qw.setId(VIEW_ID + id++); widgets.add(qw); mView.addView((View) qw, mLayout); } addView(mView); } /** * @return a HashMap of answers entered by the user for this set of widgets */ public HashMap<FormIndex, IAnswerData> getAnswers() { HashMap<FormIndex, IAnswerData> answers = new HashMap<FormIndex, IAnswerData>(); Iterator<QuestionWidget> i = widgets.iterator(); while (i.hasNext()) { /* * The FormEntryPrompt has the FormIndex, which is where the answer gets stored. The * QuestionWidget has the answer the user has entered. */ QuestionWidget q = i.next(); FormEntryPrompt p = q.getPrompt(); answers.put(p.getIndex(), q.getAnswer()); } return answers; } /** * // * Add a TextView containing the hierarchy of groups to which the question belongs. // */ private void addGroupText(FormEntryCaption[] groups) { StringBuffer s = new StringBuffer(""); String t = ""; int i; // list all groups in one string for (FormEntryCaption g : groups) { i = g.getMultiplicity() + 1; t = g.getLongText(); if (t != null) { s.append(t); if (g.repeats() && i > 0) { s.append(" (" + i + ")"); } s.append(" > "); } } // build view if (s.length() > 0) { TextView tv = new TextView(getContext()); tv.setText(s.substring(0, s.length() - 3)); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, TEXTSIZE - 4); tv.setPadding(0, 0, 0, 5); mView.addView(tv, mLayout); } } public void setFocus(Context context) { if (widgets.size() > 0) { widgets.get(0).setFocus(context); } } /** * Called when another activity returns information to answer this question. * * @param answer */ public void setBinaryData(Object answer) { boolean set = false; for (QuestionWidget q : widgets) { if (q instanceof IBinaryWidget) { if (((IBinaryWidget) q).isWaitingForBinaryData()) { ((IBinaryWidget) q).setBinaryData(answer); set = true; break; } } } if (!set) { Log.w(t, "Attempting to return data to a widget or set of widgets no looking for data"); } } /** * @return true if the answer was cleared, false otherwise. */ public boolean clearAnswer() { // If there's only one widget, clear the answer. // If there are more, then force a long-press to clear the answer. if (widgets.size() == 1 && !widgets.get(0).getPrompt().isReadOnly()) { widgets.get(0).clearAnswer(); return true; } else { return false; } } public ArrayList<QuestionWidget> getWidgets() { return widgets; } @Override public void setOnFocusChangeListener(OnFocusChangeListener l) { for (int i = 0; i < widgets.size(); i++) { QuestionWidget qw = widgets.get(i); qw.setOnFocusChangeListener(l); } } @Override public boolean onLongClick(View v) { return false; } @Override public void cancelLongPress() { super.cancelLongPress(); for (QuestionWidget qw : widgets) { qw.cancelLongPress(); } } }