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);
}
}
}
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);
}
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();
}
}
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);
}
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();
}
}
Aggregations