Search in sources :

Example 1 with FormEntryCaption

use of org.javarosa.form.api.FormEntryCaption in project collect by opendatakit.

the class ODKView method getGroupsPath.

@NonNull
public static String getGroupsPath(FormEntryCaption[] groups) {
    StringBuilder path = new StringBuilder("");
    if (groups != null) {
        String longText;
        int multiplicity;
        int index = 1;
        // list all groups in one string
        for (FormEntryCaption group : groups) {
            multiplicity = group.getMultiplicity() + 1;
            longText = group.getLongText();
            if (longText != null) {
                path.append(longText);
                if (group.repeats() && multiplicity > 0) {
                    path.append(" (").append(multiplicity).append(")");
                }
                if (index < groups.length) {
                    path.append(" > ");
                }
                index++;
            }
        }
    }
    return path.toString();
}
Also used : FormEntryCaption(org.javarosa.form.api.FormEntryCaption) SuppressLint(android.annotation.SuppressLint) NonNull(android.support.annotation.NonNull)

Example 2 with FormEntryCaption

use of org.javarosa.form.api.FormEntryCaption in project collect by opendatakit.

the class FormEntryActivity method createView.

/**
 * Creates a view given the View type and an event
 *
 * @param advancingPage -- true if this results from advancing through the form
 * @return newly created View
 */
private View createView(int event, boolean advancingPage) {
    FormController formController = getFormController();
    setTitle(formController.getFormTitle());
    formController.getTimerLogger().logTimerEvent(TimerLogger.EventTypes.FEC, event, formController.getFormIndex().getReference(), advancingPage, true);
    switch(event) {
        case FormEntryController.EVENT_BEGINNING_OF_FORM:
            return createViewForFormBeginning(event, true, formController);
        case FormEntryController.EVENT_END_OF_FORM:
            View endView = View.inflate(this, R.layout.form_entry_end, null);
            ((TextView) endView.findViewById(R.id.description)).setText(getString(R.string.save_enter_data_description, formController.getFormTitle()));
            // checkbox for if finished or ready to send
            final CheckBox instanceComplete = endView.findViewById(R.id.mark_finished);
            instanceComplete.setChecked(InstancesDaoHelper.isInstanceComplete(true));
            if (!(boolean) AdminSharedPreferences.getInstance().get(AdminKeys.KEY_MARK_AS_FINALIZED)) {
                instanceComplete.setVisibility(View.GONE);
            }
            // edittext to change the displayed name of the instance
            final EditText saveAs = endView.findViewById(R.id.save_name);
            // disallow carriage returns in the name
            InputFilter returnFilter = new InputFilter() {

                public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                    for (int i = start; i < end; i++) {
                        if (Character.getType((source.charAt(i))) == Character.CONTROL) {
                            return "";
                        }
                    }
                    return null;
                }
            };
            saveAs.setFilters(new InputFilter[] { returnFilter });
            if (formController.getSubmissionMetadata().instanceName == null) {
                // no meta/instanceName field in the form -- see if we have a
                // name for this instance from a previous save attempt...
                String uriMimeType = null;
                Uri instanceUri = getIntent().getData();
                if (instanceUri != null) {
                    uriMimeType = getContentResolver().getType(instanceUri);
                }
                if (saveName == null && uriMimeType != null && uriMimeType.equals(InstanceColumns.CONTENT_ITEM_TYPE)) {
                    Cursor instance = null;
                    try {
                        instance = getContentResolver().query(instanceUri, null, null, null, null);
                        if (instance != null && instance.getCount() == 1) {
                            instance.moveToFirst();
                            saveName = instance.getString(instance.getColumnIndex(InstanceColumns.DISPLAY_NAME));
                        }
                    } finally {
                        if (instance != null) {
                            instance.close();
                        }
                    }
                }
                if (saveName == null) {
                    // last resort, default to the form title
                    saveName = formController.getFormTitle();
                }
                // present the prompt to allow user to name the form
                TextView sa = endView.findViewById(R.id.save_form_as);
                sa.setVisibility(View.VISIBLE);
                saveAs.setText(saveName);
                saveAs.setEnabled(true);
                saveAs.setVisibility(View.VISIBLE);
                saveAs.addTextChangedListener(new TextWatcher() {

                    @Override
                    public void afterTextChanged(Editable s) {
                        saveName = String.valueOf(s);
                    }

                    @Override
                    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    }

                    @Override
                    public void onTextChanged(CharSequence s, int start, int before, int count) {
                    }
                });
            } else {
                // if instanceName is defined in form, this is the name -- no
                // revisions
                // display only the name, not the prompt, and disable edits
                saveName = formController.getSubmissionMetadata().instanceName;
                TextView sa = endView.findViewById(R.id.save_form_as);
                sa.setVisibility(View.GONE);
                saveAs.setText(saveName);
                saveAs.setEnabled(false);
                saveAs.setVisibility(View.VISIBLE);
            }
            // override the visibility settings based upon admin preferences
            if (!(boolean) AdminSharedPreferences.getInstance().get(AdminKeys.KEY_SAVE_AS)) {
                saveAs.setVisibility(View.GONE);
                TextView sa = endView.findViewById(R.id.save_form_as);
                sa.setVisibility(View.GONE);
            }
            // Create 'save' button
            endView.findViewById(R.id.save_exit_button).setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    Collect.getInstance().getActivityLogger().logInstanceAction(this, "createView.saveAndExit", instanceComplete.isChecked() ? "saveAsComplete" : "saveIncomplete");
                    // Form is marked as 'saved' here.
                    if (saveAs.getText().length() < 1) {
                        ToastUtils.showShortToast(R.string.save_as_error);
                    } else {
                        saveDataToDisk(EXIT, instanceComplete.isChecked(), saveAs.getText().toString());
                    }
                }
            });
            if (showNavigationButtons) {
                backButton.setEnabled(allowMovingBackwards);
                nextButton.setEnabled(false);
            }
            return endView;
        case FormEntryController.EVENT_QUESTION:
        case FormEntryController.EVENT_GROUP:
        case FormEntryController.EVENT_REPEAT:
            releaseOdkView();
            // should only be a group here if the event_group is a field-list
            try {
                FormEntryPrompt[] prompts = formController.getQuestionPrompts();
                FormEntryCaption[] groups = formController.getGroupsForCurrentIndex();
                odkView = new ODKView(this, prompts, groups, advancingPage);
                Timber.i("Created view for group %s %s", (groups.length > 0 ? groups[groups.length - 1].getLongText() : "[top]"), (prompts.length > 0 ? prompts[0].getQuestionText() : "[no question]"));
            } catch (RuntimeException e) {
                Timber.e(e);
                // this is badness to avoid a crash.
                try {
                    event = formController.stepToNextScreenEvent();
                    createErrorDialog(e.getMessage(), DO_NOT_EXIT);
                } catch (JavaRosaException e1) {
                    Timber.d(e1);
                    createErrorDialog(e.getMessage() + "\n\n" + e1.getCause().getMessage(), DO_NOT_EXIT);
                }
                return createView(event, advancingPage);
            }
            // Makes a "clear answer" menu pop up on long-click
            for (QuestionWidget qw : odkView.getWidgets()) {
                if (!qw.getFormEntryPrompt().isReadOnly()) {
                    // we want to enable paste option after long click on the EditText
                    if (qw instanceof StringWidget) {
                        for (int i = 0; i < qw.getChildCount(); i++) {
                            if (!(qw.getChildAt(i) instanceof EditText)) {
                                registerForContextMenu(qw.getChildAt(i));
                            }
                        }
                    } else {
                        registerForContextMenu(qw);
                    }
                }
            }
            if (showNavigationButtons) {
                backButton.setEnabled(!formController.isCurrentQuestionFirstInForm() && allowMovingBackwards);
                nextButton.setEnabled(true);
            }
            return odkView;
        case FormEntryController.EVENT_PROMPT_NEW_REPEAT:
            createRepeatDialog();
            return new EmptyView(this);
        default:
            Timber.e("Attempted to create a view that does not exist.");
            // this is badness to avoid a crash.
            try {
                event = formController.stepToNextScreenEvent();
                createErrorDialog(getString(R.string.survey_internal_error), EXIT);
            } catch (JavaRosaException e) {
                Timber.d(e);
                createErrorDialog(e.getCause().getMessage(), EXIT);
            }
            return createView(event, advancingPage);
    }
}
Also used : FormEntryPrompt(org.javarosa.form.api.FormEntryPrompt) ODKView(org.odk.collect.android.views.ODKView) FormEntryCaption(org.javarosa.form.api.FormEntryCaption) Cursor(android.database.Cursor) Uri(android.net.Uri) TextWatcher(android.text.TextWatcher) Editable(android.text.Editable) TextView(android.widget.TextView) StringWidget(org.odk.collect.android.widgets.StringWidget) QuestionWidget(org.odk.collect.android.widgets.QuestionWidget) FormController(org.odk.collect.android.logic.FormController) EditText(android.widget.EditText) InputFilter(android.text.InputFilter) ODKView(org.odk.collect.android.views.ODKView) View(android.view.View) AdapterView(android.widget.AdapterView) TextView(android.widget.TextView) ListView(android.widget.ListView) Spanned(android.text.Spanned) FailedConstraint(org.odk.collect.android.logic.FormController.FailedConstraint) CheckBox(android.widget.CheckBox) OnClickListener(android.view.View.OnClickListener) JavaRosaException(org.odk.collect.android.exception.JavaRosaException)

Example 3 with FormEntryCaption

use of org.javarosa.form.api.FormEntryCaption in project collect by opendatakit.

the class FormHierarchyActivity method getCurrentPath.

private String getCurrentPath() {
    FormController formController = Collect.getInstance().getFormController();
    FormIndex index = formController.getFormIndex();
    // move to enclosing group...
    index = formController.stepIndexOut(index);
    List<FormEntryCaption> groups = new ArrayList<>();
    while (index != null) {
        groups.add(0, formController.getCaptionPrompt(index));
        index = formController.stepIndexOut(index);
    }
    return ODKView.getGroupsPath(groups.toArray(new FormEntryCaption[groups.size()]));
}
Also used : FormController(org.odk.collect.android.logic.FormController) FormEntryCaption(org.javarosa.form.api.FormEntryCaption) ArrayList(java.util.ArrayList) FormIndex(org.javarosa.core.model.FormIndex)

Example 4 with FormEntryCaption

use of org.javarosa.form.api.FormEntryCaption 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 5 with FormEntryCaption

use of org.javarosa.form.api.FormEntryCaption 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)

Aggregations

FormEntryCaption (org.javarosa.form.api.FormEntryCaption)7 FormIndex (org.javarosa.core.model.FormIndex)4 GroupDef (org.javarosa.core.model.GroupDef)3 FormController (org.odk.collect.android.logic.FormController)3 FormEntryPrompt (org.javarosa.form.api.FormEntryPrompt)2 JavaRosaException (org.odk.collect.android.exception.JavaRosaException)2 SuppressLint (android.annotation.SuppressLint)1 Cursor (android.database.Cursor)1 Uri (android.net.Uri)1 NonNull (android.support.annotation.NonNull)1 Editable (android.text.Editable)1 InputFilter (android.text.InputFilter)1 Spanned (android.text.Spanned)1 TextWatcher (android.text.TextWatcher)1 View (android.view.View)1 OnClickListener (android.view.View.OnClickListener)1 AdapterView (android.widget.AdapterView)1 CheckBox (android.widget.CheckBox)1 EditText (android.widget.EditText)1 ListView (android.widget.ListView)1