Search in sources :

Example 36 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormHierarchyActivity method refreshView.

public void refreshView() {
    try {
        FormController formController = Collect.getInstance().getFormController();
        // Record the current index so we can return to the same place if the user hits 'back'.
        currentIndex = formController.getFormIndex();
        // If we're not at the first level, we're inside a repeated group so we want to only
        // display
        // everything enclosed within that group.
        String contextGroupRef = "";
        formList = new ArrayList<HierarchyElement>();
        // node to display.
        if (formController.getEvent() == FormEntryController.EVENT_REPEAT) {
            contextGroupRef = formController.getFormIndex().getReference().toString(true);
            formController.stepToNextEvent(FormController.STEP_INTO_GROUP);
        } else {
            FormIndex startTest = formController.stepIndexOut(currentIndex);
            // beginning.
            while (startTest != null && formController.getEvent(startTest) == FormEntryController.EVENT_GROUP) {
                startTest = formController.stepIndexOut(startTest);
            }
            if (startTest == null) {
                // check to see if the question is at the first level of the hierarchy. If it
                // is,
                // display the root level from the beginning.
                formController.jumpToIndex(FormIndex.createBeginningOfFormIndex());
            } else {
                // otherwise we're at a repeated group
                formController.jumpToIndex(startTest);
            }
            // beginning
            if (formController.getEvent() == FormEntryController.EVENT_REPEAT) {
                contextGroupRef = formController.getFormIndex().getReference().toString(true);
                formController.stepToNextEvent(FormController.STEP_INTO_GROUP);
            }
        }
        int event = formController.getEvent();
        if (event == FormEntryController.EVENT_BEGINNING_OF_FORM) {
            // The beginning of form has no valid prompt to display.
            formController.stepToNextEvent(FormController.STEP_INTO_GROUP);
            contextGroupRef = formController.getFormIndex().getReference().getParentRef().toString(true);
            path.setVisibility(View.GONE);
            jumpPreviousButton.setEnabled(false);
        } else {
            path.setVisibility(View.VISIBLE);
            path.setText(getCurrentPath());
            jumpPreviousButton.setEnabled(true);
        }
        // Refresh the current event in case we did step forward.
        event = formController.getEvent();
        // Big change from prior implementation:
        // 
        // The ref strings now include the instance number designations
        // i.e., [0], [1], etc. of the repeat groups (and also [1] for
        // non-repeat elements).
        // 
        // The contextGroupRef is now also valid for the top-level form.
        // 
        // The repeatGroupRef is null if we are not skipping a repeat
        // section.
        // 
        String repeatGroupRef = null;
        event_search: while (event != FormEntryController.EVENT_END_OF_FORM) {
            // get the ref to this element
            String currentRef = formController.getFormIndex().getReference().toString(true);
            // retrieve the current group
            String curGroup = (repeatGroupRef == null) ? contextGroupRef : repeatGroupRef;
            if (!currentRef.startsWith(curGroup)) {
                // We have left the current group
                if (repeatGroupRef == null) {
                    // We are done.
                    break;
                } else {
                    // exit the inner repeat group
                    repeatGroupRef = null;
                }
            }
            if (repeatGroupRef != null) {
                // We're in a repeat group within the one we want to list
                // skip this question/group/repeat and move to the next index.
                event = formController.stepToNextEvent(FormController.STEP_INTO_GROUP);
                continue;
            }
            switch(event) {
                case FormEntryController.EVENT_QUESTION:
                    FormEntryPrompt fp = formController.getQuestionPrompt();
                    String label = fp.getLongText();
                    if (!fp.isReadOnly() || (label != null && label.length() > 0)) {
                        // show the question if it is an editable field.
                        // or if it is read-only and the label is not blank.
                        String answerDisplay = FormEntryPromptUtils.getAnswerText(fp, this, formController);
                        formList.add(new HierarchyElement(FormEntryPromptUtils.markQuestionIfIsRequired(label, fp.isRequired()), answerDisplay, null, Color.WHITE, QUESTION, fp.getIndex()));
                    }
                    break;
                case FormEntryController.EVENT_GROUP:
                    // ignore group events
                    break;
                case FormEntryController.EVENT_PROMPT_NEW_REPEAT:
                    // ignore it.
                    break;
                case FormEntryController.EVENT_REPEAT:
                    FormEntryCaption fc = formController.getCaptionPrompt();
                    // push this repeat onto the stack.
                    repeatGroupRef = currentRef;
                    if (fc.getMultiplicity() == 0) {
                        // Display the repeat header for the group.
                        HierarchyElement group = new HierarchyElement(fc.getLongText(), null, ContextCompat.getDrawable(getApplicationContext(), R.drawable.expander_ic_minimized), Color.WHITE, COLLAPSED, fc.getIndex());
                        formList.add(group);
                    }
                    String repeatLabel = mIndent + fc.getLongText();
                    if (fc.getFormElement().getChildren().size() == 1 && fc.getFormElement().getChild(0) instanceof GroupDef) {
                        formController.stepToNextEvent(FormController.STEP_INTO_GROUP);
                        FormEntryCaption fc2 = formController.getCaptionPrompt();
                        if (fc2.getLongText() != null) {
                            repeatLabel = fc2.getLongText();
                        }
                    }
                    repeatLabel += " (" + (fc.getMultiplicity() + 1) + ")";
                    // Add this group name to the drop down list for this repeating group.
                    HierarchyElement h = formList.get(formList.size() - 1);
                    h.addChild(new HierarchyElement(repeatLabel, null, null, Color.WHITE, CHILD, fc.getIndex()));
                    break;
            }
            event = formController.stepToNextEvent(FormController.STEP_INTO_GROUP);
        }
        HierarchyListAdapter itla = new HierarchyListAdapter(this);
        itla.setListItems(formList);
        listView.setAdapter(itla);
        // set the controller back to the current index in case the user hits 'back'
        formController.jumpToIndex(currentIndex);
    } catch (Exception e) {
        Timber.e(e);
        createErrorDialog(e.getMessage());
    }
}
Also used : FormController(org.odk.collect.android.logic.FormController) FormEntryPrompt(org.javarosa.form.api.FormEntryPrompt) HierarchyElement(org.odk.collect.android.logic.HierarchyElement) HierarchyListAdapter(org.odk.collect.android.adapters.HierarchyListAdapter) FormEntryCaption(org.javarosa.form.api.FormEntryCaption) FormIndex(org.javarosa.core.model.FormIndex) GroupDef(org.javarosa.core.model.GroupDef)

Example 37 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormController method saveAllScreenAnswers.

/**
 * @return FailedConstraint of first failed constraint or null if all questions were saved.
 */
public FailedConstraint saveAllScreenAnswers(HashMap<FormIndex, IAnswerData> answers, boolean evaluateConstraints) throws JavaRosaException {
    if (currentPromptIsQuestion()) {
        for (FormIndex index : answers.keySet()) {
            // Within a group, you can only save for question events
            if (getEvent(index) == FormEntryController.EVENT_QUESTION) {
                int saveStatus;
                IAnswerData answer = answers.get(index);
                if (evaluateConstraints) {
                    saveStatus = answerQuestion(index, answer);
                    if (saveStatus != FormEntryController.ANSWER_OK) {
                        return new FailedConstraint(index, saveStatus);
                    }
                } else {
                    saveAnswer(index, answer);
                }
            } else {
                Timber.w("Attempted to save an index referencing something other than a question: %s", index.getReference().toString());
            }
        }
    }
    return null;
}
Also used : IAnswerData(org.javarosa.core.model.data.IAnswerData) FormIndex(org.javarosa.core.model.FormIndex)

Example 38 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormController method stepToPreviousScreenEvent.

/**
 * Move the current form index to the index of the previous question in the form.
 * Step backward out of repeats and groups as needed. If the resulting question
 * is itself within a field-list, move upward to the group or repeat defining that
 * field-list.
 */
public int stepToPreviousScreenEvent() throws JavaRosaException {
    try {
        if (getEvent() != FormEntryController.EVENT_BEGINNING_OF_FORM) {
            int event = stepToPreviousEvent();
            while (event == FormEntryController.EVENT_REPEAT_JUNCTURE || event == FormEntryController.EVENT_PROMPT_NEW_REPEAT || (event == FormEntryController.EVENT_QUESTION && indexIsInFieldList()) || ((event == FormEntryController.EVENT_GROUP || event == FormEntryController.EVENT_REPEAT) && !indexIsInFieldList())) {
                event = stepToPreviousEvent();
            }
            // Handle nested field-list group
            if (getEvent() == FormEntryController.EVENT_GROUP) {
                FormIndex currentIndex = getFormIndex();
                IFormElement element = formEntryController.getModel().getForm().getChild(currentIndex);
                if (element instanceof GroupDef) {
                    GroupDef gd = (GroupDef) element;
                    if (ODKView.FIELD_LIST.equalsIgnoreCase(gd.getAppearanceAttr())) {
                        // jump to outermost containing field-list
                        FormEntryCaption[] fclist = this.getCaptionHierarchy(currentIndex);
                        for (FormEntryCaption caption : fclist) {
                            if (groupIsFieldList(caption.getIndex())) {
                                formEntryController.jumpToIndex(caption.getIndex());
                                break;
                            }
                        }
                    }
                }
            }
        }
        return getEvent();
    } catch (RuntimeException e) {
        throw new JavaRosaException(e);
    }
}
Also used : IFormElement(org.javarosa.core.model.IFormElement) FormEntryCaption(org.javarosa.form.api.FormEntryCaption) FormIndex(org.javarosa.core.model.FormIndex) GroupDef(org.javarosa.core.model.GroupDef) JavaRosaException(org.odk.collect.android.exception.JavaRosaException)

Example 39 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormController method getIndicesForGroup.

private List<FormIndex> getIndicesForGroup(GroupDef gd, FormIndex currentChildIndex) {
    List<FormIndex> indices = new ArrayList<>();
    for (int i = 0; i < gd.getChildren().size(); i++) {
        final FormEntryModel formEntryModel = formEntryController.getModel();
        if (getEvent(currentChildIndex) == FormEntryController.EVENT_GROUP) {
            IFormElement nestedElement = formEntryModel.getForm().getChild(currentChildIndex);
            if (nestedElement instanceof GroupDef) {
                indices.addAll(getIndicesForGroup((GroupDef) nestedElement, formEntryModel.incrementIndex(currentChildIndex, true)));
                currentChildIndex = formEntryModel.incrementIndex(currentChildIndex, false);
            }
        } else {
            indices.add(currentChildIndex);
            currentChildIndex = formEntryModel.incrementIndex(currentChildIndex, false);
        }
    }
    return indices;
}
Also used : IFormElement(org.javarosa.core.model.IFormElement) FormEntryModel(org.javarosa.form.api.FormEntryModel) ArrayList(java.util.ArrayList) FormIndex(org.javarosa.core.model.FormIndex) GroupDef(org.javarosa.core.model.GroupDef)

Example 40 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormController method stepToPreviousEvent.

/**
 * Navigates backward in the form.
 *
 * @return the event that should be handled by a view.
 */
public int stepToPreviousEvent() {
    /*
         * Right now this will always skip to the beginning of a group if that group is represented
         * as a 'field-list'. Should a need ever arise to step backwards by only one step in a
         * 'field-list', this method will have to be updated.
         */
    formEntryController.stepToPreviousEvent();
    if (indexIsInFieldList() && getEvent() == FormEntryController.EVENT_QUESTION) {
        // caption[0..len-1]
        // caption[len-1] == the question itself
        // caption[len-2] == the first group it is contained in.
        FormEntryCaption[] captions = getCaptionHierarchy();
        FormEntryCaption grp = captions[captions.length - 2];
        int event = formEntryController.jumpToIndex(grp.getIndex());
        // and test if this group or at least one of its children is relevant...
        FormIndex idx = grp.getIndex();
        if (!formEntryController.getModel().isIndexRelevant(idx)) {
            return stepToPreviousEvent();
        }
        idx = formEntryController.getModel().incrementIndex(idx, true);
        while (FormIndex.isSubElement(grp.getIndex(), idx)) {
            if (formEntryController.getModel().isIndexRelevant(idx)) {
                return event;
            }
            idx = formEntryController.getModel().incrementIndex(idx, true);
        }
        return stepToPreviousEvent();
    } else if (indexIsInFieldList() && getEvent() == FormEntryController.EVENT_GROUP) {
        FormIndex grpidx = formEntryController.getModel().getFormIndex();
        int event = formEntryController.getModel().getEvent();
        // and test if this group or at least one of its children is relevant...
        if (!formEntryController.getModel().isIndexRelevant(grpidx)) {
            // shouldn't happen?
            return stepToPreviousEvent();
        }
        FormIndex idx = formEntryController.getModel().incrementIndex(grpidx, true);
        while (FormIndex.isSubElement(grpidx, idx)) {
            if (formEntryController.getModel().isIndexRelevant(idx)) {
                return event;
            }
            idx = formEntryController.getModel().incrementIndex(idx, true);
        }
        return stepToPreviousEvent();
    }
    return getEvent();
}
Also used : FormEntryCaption(org.javarosa.form.api.FormEntryCaption) FormIndex(org.javarosa.core.model.FormIndex)

Aggregations

FormIndex (org.javarosa.core.model.FormIndex)63 GroupDef (org.javarosa.core.model.GroupDef)11 JavaRosaException (org.odk.collect.android.exception.JavaRosaException)11 FormController (org.odk.collect.android.javarosawrapper.FormController)11 ArrayList (java.util.ArrayList)10 FormEntryPrompt (org.javarosa.form.api.FormEntryPrompt)10 Test (org.junit.Test)10 IFormElement (org.javarosa.core.model.IFormElement)6 TreeReference (org.javarosa.core.model.instance.TreeReference)6 FormEntryCaption (org.javarosa.form.api.FormEntryCaption)6 File (java.io.File)5 FormController (org.odk.collect.android.logic.FormController)5 HierarchyElement (org.odk.collect.android.logic.HierarchyElement)5 IAnswerData (org.javarosa.core.model.data.IAnswerData)4 HierarchyListAdapter (org.odk.collect.android.adapters.HierarchyListAdapter)4 FormDef (org.javarosa.core.model.FormDef)3 FormEntryModel (org.javarosa.form.api.FormEntryModel)3 Intent (android.content.Intent)2 ObjectInputStream (java.io.ObjectInputStream)2 HashMap (java.util.HashMap)2