Search in sources :

Example 31 with FormController

use of org.odk.collect.android.javarosawrapper.FormController in project collect by opendatakit.

the class FormEntryActivity method showView.

/**
 * Displays the View specified by the parameter 'next', animating both the
 * current view and next appropriately given the AnimationType. Also updates
 * the progress bar.
 */
public void showView(View next, AnimationType from) {
    invalidateOptionsMenu();
    // disable notifications...
    if (inAnimation != null) {
        inAnimation.setAnimationListener(null);
    }
    if (outAnimation != null) {
        outAnimation.setAnimationListener(null);
    }
    // by createView()
    switch(from) {
        case RIGHT:
            inAnimation = loadAnimation(this, R.anim.push_left_in);
            outAnimation = loadAnimation(this, R.anim.push_left_out);
            // if animation is left or right then it was a swipe, and we want to re-save on
            // entry
            autoSaved = false;
            break;
        case LEFT:
            inAnimation = loadAnimation(this, R.anim.push_right_in);
            outAnimation = loadAnimation(this, R.anim.push_right_out);
            autoSaved = false;
            break;
        case FADE:
            inAnimation = loadAnimation(this, R.anim.fade_in);
            outAnimation = loadAnimation(this, R.anim.fade_out);
            break;
    }
    // complete setup for animations...
    inAnimation.setAnimationListener(this);
    outAnimation.setAnimationListener(this);
    if (!areAnimationsEnabled(this)) {
        inAnimation.setDuration(0);
        outAnimation.setDuration(0);
    }
    // drop keyboard before transition...
    if (currentView != null) {
        softKeyboardController.hideSoftKeyboard(currentView);
    }
    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    // adjust which view is in the layout container...
    View staleView = currentView;
    currentView = next;
    swipeHandler.setOdkView(getCurrentViewIfODKView());
    questionHolder.addView(currentView, lp);
    animationCompletionSet = 0;
    if (staleView != null) {
        // start OutAnimation for transition...
        staleView.startAnimation(outAnimation);
        // and remove the old view (MUST occur after start of animation!!!)
        questionHolder.removeView(staleView);
    } else {
        animationCompletionSet = 2;
    }
    // start InAnimation for transition...
    currentView.startAnimation(inAnimation);
    FormController formController = getFormController();
    if (formController.getEvent() == FormEntryController.EVENT_QUESTION || formController.getEvent() == FormEntryController.EVENT_GROUP || formController.getEvent() == FormEntryController.EVENT_REPEAT) {
        try {
            FormEntryPrompt[] prompts = getFormController().getQuestionPrompts();
            for (FormEntryPrompt p : prompts) {
                List<TreeElement> attrs = p.getBindAttributes();
                for (int i = 0; i < attrs.size(); i++) {
                    if (!autoSaved && "saveIncomplete".equals(attrs.get(i).getName())) {
                        analytics.logEvent(SAVE_INCOMPLETE, "saveIncomplete", AnalyticsUtils.getFormHash(Collect.getInstance().getFormController()));
                        saveForm(false, false, null, false);
                        autoSaved = true;
                    }
                }
            }
        } catch (RepeatsInFieldListException e) {
            createErrorDialog(e.getMessage(), false);
        }
    }
}
Also used : FormController(org.odk.collect.android.javarosawrapper.FormController) LayoutParams(android.view.ViewGroup.LayoutParams) FormEntryPrompt(org.javarosa.form.api.FormEntryPrompt) RepeatsInFieldListException(org.odk.collect.android.javarosawrapper.RepeatsInFieldListException) RelativeLayout(android.widget.RelativeLayout) ODKView(org.odk.collect.android.formentry.ODKView) FormEndView(org.odk.collect.android.formentry.FormEndView) View(android.view.View) WebView(android.webkit.WebView) AudioControllerView(org.odk.collect.android.audio.AudioControllerView) TextView(android.widget.TextView) FailedConstraint(org.odk.collect.android.javarosawrapper.FormController.FailedConstraint) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 32 with FormController

use of org.odk.collect.android.javarosawrapper.FormController in project collect by opendatakit.

the class FormEntryActivity method updateNavigationButtonVisibility.

/**
 * Shows the next or back button, neither or both. Both buttons are displayed unless:
 * - we are at the first question in the form so the back button is hidden
 * - we are at the end screen so the next button is hidden
 * - settings prevent backwards navigation of the form so the back button is hidden
 * <p>
 * The visibility of the container for these buttons is determined once {@link #onResume()}.
 */
private void updateNavigationButtonVisibility() {
    FormController formController = getFormController();
    if (formController == null) {
        return;
    }
    backButton.setVisibility(!formController.isCurrentQuestionFirstInForm() && allowMovingBackwards ? View.VISIBLE : View.GONE);
    nextButton.setVisibility(formController.getEvent() != FormEntryController.EVENT_END_OF_FORM ? View.VISIBLE : View.GONE);
}
Also used : FormController(org.odk.collect.android.javarosawrapper.FormController)

Example 33 with FormController

use of org.odk.collect.android.javarosawrapper.FormController in project collect by opendatakit.

the class FormEntryActivity method deleteGroup.

@Override
public void deleteGroup() {
    FormController formController = getFormController();
    if (formController != null && !formController.indexIsInFieldList()) {
        swipeHandler.setBeenSwiped(true);
        onSwipeForward();
    } else {
        onScreenRefresh();
    }
}
Also used : FormController(org.odk.collect.android.javarosawrapper.FormController)

Example 34 with FormController

use of org.odk.collect.android.javarosawrapper.FormController in project collect by opendatakit.

the class FormEntryActivity method createConstraintToast.

/**
 * Creates and displays a dialog displaying the violated constraint.
 */
private void createConstraintToast(FormIndex index, int saveStatus) {
    FormController formController = getFormController();
    String constraintText;
    switch(saveStatus) {
        case FormEntryController.ANSWER_CONSTRAINT_VIOLATED:
            constraintText = formController.getQuestionPromptConstraintText(index);
            if (constraintText == null) {
                constraintText = formController.getQuestionPrompt(index).getSpecialFormQuestionText("constraintMsg");
                if (constraintText == null) {
                    constraintText = getString(R.string.invalid_answer_error);
                }
            }
            break;
        case FormEntryController.ANSWER_REQUIRED_BUT_EMPTY:
            constraintText = formController.getQuestionPromptRequiredText(index);
            if (constraintText == null) {
                constraintText = formController.getQuestionPrompt(index).getSpecialFormQuestionText("requiredMsg");
                if (constraintText == null) {
                    constraintText = getString(R.string.required_answer_error);
                }
            }
            break;
        default:
            return;
    }
    ToastUtils.showShortToastInMiddle(this, constraintText);
}
Also used : FormController(org.odk.collect.android.javarosawrapper.FormController)

Example 35 with FormController

use of org.odk.collect.android.javarosawrapper.FormController in project collect by opendatakit.

the class FormEntryActivity method loadingComplete.

/**
 * Given a {@link FormLoaderTask} which has created a {@link FormController} for either a new or
 * existing instance, shows that instance to the user. Either launches {@link FormHierarchyActivity}
 * if an existing instance is being edited or builds the view for the current question(s) if a
 * new instance is being created.
 * <p>
 * May do some or all of these depending on current state:
 * - Ensures phone state permissions are given if this form needs them
 * - Cleans up {@link #formLoaderTask}
 * - Sets the global form controller and database manager for search()/pulldata()
 * - Restores the last-used language
 * - Handles activity results that may have come in while the form was loading
 * - Alerts the user of a recovery from savepoint
 * - Verifies whether an instance folder exists and creates one if not
 * - Initializes background location capture (only if the instance being loaded is a new one)
 */
@Override
public void loadingComplete(FormLoaderTask task, FormDef formDef, String warningMsg) {
    DialogFragmentUtils.dismissDialog(FormLoadingDialogFragment.class, getSupportFragmentManager());
    final FormController formController = task.getFormController();
    if (formController != null) {
        if (readPhoneStatePermissionRequestNeeded) {
            permissionsProvider.requestReadPhoneStatePermission(this, true, new PermissionListener() {

                @Override
                public void granted() {
                    readPhoneStatePermissionRequestNeeded = false;
                    loadForm();
                }

                @Override
                public void denied() {
                    finish();
                }
            });
        } else {
            formLoaderTask.setFormLoaderListener(null);
            FormLoaderTask t = formLoaderTask;
            formLoaderTask = null;
            t.cancel(true);
            t.destroy();
            Collect.getInstance().setFormController(formController);
            backgroundLocationViewModel.formFinishedLoading();
            Collect.getInstance().setExternalDataManager(task.getExternalDataManager());
            // Set the language if one has already been set in the past
            String[] languageTest = formController.getLanguages();
            if (languageTest != null) {
                String defaultLanguage = formController.getLanguage();
                Form form = formsRepository.getOneByPath(formPath);
                if (form != null) {
                    String newLanguage = form.getLanguage();
                    try {
                        formController.setLanguage(newLanguage);
                    } catch (Exception e) {
                        // if somehow we end up with a bad language, set it to the default
                        Timber.i("Ended up with a bad language. %s", newLanguage);
                        formController.setLanguage(defaultLanguage);
                    }
                }
            }
            boolean pendingActivityResult = task.hasPendingActivityResult();
            if (pendingActivityResult) {
                Timber.w("Calling onActivityResult from loadingComplete");
                formControllerAvailable(formController);
                onScreenRefresh();
                onActivityResult(task.getRequestCode(), task.getResultCode(), task.getIntent());
                return;
            }
            // it can be a normal flow for a pending activity result to restore from a savepoint
            // (the call flow handled by the above if statement). For all other use cases, the
            // user should be notified, as it means they wandered off doing other things then
            // returned to ODK Collect and chose Edit Saved Form, but that the savepoint for
            // that form is newer than the last saved version of their form data.
            boolean hasUsedSavepoint = task.hasUsedSavepoint();
            if (hasUsedSavepoint) {
                runOnUiThread(() -> showLongToast(this, R.string.savepoint_used));
            }
            if (formController.getInstanceFile() == null) {
                FormInstanceFileCreator formInstanceFileCreator = new FormInstanceFileCreator(storagePathProvider, System::currentTimeMillis);
                File instanceFile = formInstanceFileCreator.createInstanceFile(formPath);
                if (instanceFile != null) {
                    formController.setInstanceFile(instanceFile);
                } else {
                    showFormLoadErrorAndExit(getString(R.string.loading_form_failed));
                }
                formControllerAvailable(formController);
                identityPromptViewModel.requiresIdentityToContinue().observe(this, requiresIdentity -> {
                    if (!requiresIdentity) {
                        formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.FORM_START, true, System.currentTimeMillis());
                        startFormEntry(formController, warningMsg);
                    }
                });
            } else {
                Intent reqIntent = getIntent();
                boolean showFirst = reqIntent.getBooleanExtra("start", false);
                if (!showFirst) {
                    // we've just loaded a saved form, so start in the hierarchy view
                    String formMode = reqIntent.getStringExtra(ApplicationConstants.BundleKeys.FORM_MODE);
                    if (formMode == null || ApplicationConstants.FormModes.EDIT_SAVED.equalsIgnoreCase(formMode)) {
                        formControllerAvailable(formController);
                        identityPromptViewModel.requiresIdentityToContinue().observe(this, requiresIdentity -> {
                            if (!requiresIdentity) {
                                if (!allowMovingBackwards) {
                                    // we aren't allowed to jump around the form so attempt to
                                    // go directly to the question we were on last time the
                                    // form was saved.
                                    // TODO: revisit the fallback. If for some reason the index
                                    // wasn't saved, we can now jump around which doesn't seem right.
                                    FormIndex formIndex = SaveFormIndexTask.loadFormIndexFromFile();
                                    if (formIndex != null) {
                                        formController.jumpToIndex(formIndex);
                                        onScreenRefresh();
                                        return;
                                    }
                                }
                                formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.FORM_RESUME, true, System.currentTimeMillis());
                                formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.HIERARCHY, true, System.currentTimeMillis());
                                startActivityForResult(new Intent(this, FormHierarchyActivity.class), RequestCodes.HIERARCHY_ACTIVITY);
                            }
                        });
                        formSaveViewModel.editingForm();
                    } else {
                        if (ApplicationConstants.FormModes.VIEW_SENT.equalsIgnoreCase(formMode)) {
                            startActivity(new Intent(this, ViewOnlyFormHierarchyActivity.class));
                        }
                        finish();
                    }
                } else {
                    formControllerAvailable(formController);
                    identityPromptViewModel.requiresIdentityToContinue().observe(this, requiresIdentity -> {
                        if (!requiresIdentity) {
                            formController.getAuditEventLogger().logEvent(AuditEvent.AuditEventType.FORM_RESUME, true, System.currentTimeMillis());
                            startFormEntry(formController, warningMsg);
                        }
                    });
                }
            }
        }
    } else {
        Timber.e("FormController is null");
        showLongToast(this, R.string.loading_form_failed);
        finish();
    }
}
Also used : FormController(org.odk.collect.android.javarosawrapper.FormController) PermissionListener(org.odk.collect.permissions.PermissionListener) FormInstanceFileCreator(org.odk.collect.android.formentry.loading.FormInstanceFileCreator) Form(org.odk.collect.forms.Form) Intent(android.content.Intent) RepeatsInFieldListException(org.odk.collect.android.javarosawrapper.RepeatsInFieldListException) JavaRosaException(org.odk.collect.android.exception.JavaRosaException) FormLoaderTask(org.odk.collect.android.tasks.FormLoaderTask) FormIndex(org.javarosa.core.model.FormIndex) File(java.io.File)

Aggregations

FormController (org.odk.collect.android.javarosawrapper.FormController)53 FormIndex (org.javarosa.core.model.FormIndex)11 File (java.io.File)9 JavaRosaException (org.odk.collect.android.exception.JavaRosaException)9 FormDef (org.javarosa.core.model.FormDef)4 FormEntryPrompt (org.javarosa.form.api.FormEntryPrompt)4 Collect (org.odk.collect.android.application.Collect)4 RepeatsInFieldListException (org.odk.collect.android.javarosawrapper.RepeatsInFieldListException)4 LocalizedApplicationKt.getLocalizedString (org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString)4 TextView (android.widget.TextView)3 ArrayList (java.util.ArrayList)3 FormInstance (org.javarosa.core.model.instance.FormInstance)3 TreeReference (org.javarosa.core.model.instance.TreeReference)3 FormEntryCaption (org.javarosa.form.api.FormEntryCaption)3 Before (org.junit.Before)3 Test (org.junit.Test)3 Form (org.odk.collect.forms.Form)3 Intent (android.content.Intent)2 View (android.view.View)2 WebView (android.webkit.WebView)2