use of org.odk.collect.android.logic.HierarchyElement in project collect by opendatakit.
the class EditFormHierarchyActivity method onItemClick.
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
HierarchyElement h = (HierarchyElement) listView.getItemAtPosition(position);
FormIndex index = h.getFormIndex();
if (index == null) {
goUpLevel();
return;
}
switch(h.getType()) {
case EXPANDED:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onListItemClick", "COLLAPSED", h.getFormIndex());
h.setType(COLLAPSED);
ArrayList<HierarchyElement> children = h.getChildren();
for (int i = 0; i < children.size(); i++) {
formList.remove(position + 1);
}
h.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.expander_ic_minimized));
break;
case COLLAPSED:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onListItemClick", "EXPANDED", h.getFormIndex());
h.setType(EXPANDED);
ArrayList<HierarchyElement> children1 = h.getChildren();
for (int i = 0; i < children1.size(); i++) {
Timber.i("adding child: %s", children1.get(i).getFormIndex());
formList.add(position + 1 + i, children1.get(i));
}
h.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.expander_ic_maximized));
break;
case QUESTION:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onListItemClick", "QUESTION-JUMP", index);
Collect.getInstance().getFormController().jumpToIndex(index);
if (Collect.getInstance().getFormController().indexIsInFieldList()) {
try {
Collect.getInstance().getFormController().stepToPreviousScreenEvent();
} catch (JavaRosaException e) {
Timber.d(e);
createErrorDialog(e.getCause().getMessage());
return;
}
}
setResult(RESULT_OK);
finish();
return;
case CHILD:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onListItemClick", "REPEAT-JUMP", h.getFormIndex());
Collect.getInstance().getFormController().jumpToIndex(h.getFormIndex());
setResult(RESULT_OK);
refreshView();
return;
}
// Should only get here if we've expanded or collapsed a group
HierarchyListAdapter itla = new HierarchyListAdapter(this);
itla.setListItems(formList);
listView.setAdapter(itla);
listView.setSelection(position);
}
use of org.odk.collect.android.logic.HierarchyElement in project collect by opendatakit.
the class ViewFormHierarchyActivity method onItemClick.
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
HierarchyElement h = (HierarchyElement) listView.getItemAtPosition(position);
FormIndex index = h.getFormIndex();
if (index == null) {
goUpLevel();
return;
}
switch(h.getType()) {
case EXPANDED:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onListItemClick", "COLLAPSED", h.getFormIndex());
h.setType(COLLAPSED);
ArrayList<HierarchyElement> children = h.getChildren();
for (int i = 0; i < children.size(); i++) {
formList.remove(position + 1);
}
h.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.expander_ic_minimized));
break;
case COLLAPSED:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onListItemClick", "EXPANDED", h.getFormIndex());
h.setType(EXPANDED);
ArrayList<HierarchyElement> children1 = h.getChildren();
for (int i = 0; i < children1.size(); i++) {
Timber.i("adding child: %s", children1.get(i).getFormIndex());
formList.add(position + 1 + i, children1.get(i));
}
h.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.expander_ic_maximized));
break;
case QUESTION:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onListItemClick", "QUESTION-JUMP", index);
Collect.getInstance().getFormController().jumpToIndex(index);
if (Collect.getInstance().getFormController().indexIsInFieldList()) {
try {
Collect.getInstance().getFormController().stepToPreviousScreenEvent();
} catch (JavaRosaException e) {
Timber.d(e);
createErrorDialog(e.getCause().getMessage());
return;
}
}
setResult(RESULT_OK);
return;
case CHILD:
Collect.getInstance().getActivityLogger().logInstanceAction(this, "onListItemClick", "REPEAT-JUMP", h.getFormIndex());
Collect.getInstance().getFormController().jumpToIndex(h.getFormIndex());
setResult(RESULT_OK);
refreshView();
return;
}
// Should only get here if we've expanded or collapsed a group
HierarchyListAdapter itla = new HierarchyListAdapter(this);
itla.setListItems(formList);
listView.setAdapter(itla);
listView.setSelection(position);
}
use of org.odk.collect.android.logic.HierarchyElement in project collect by opendatakit.
the class FormHierarchyActivity method onCreate.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.hierarchy_layout);
Collect.getInstance().getComponent().inject(this);
recyclerView = findViewById(R.id.list);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
TextView emptyView = findViewById(android.R.id.empty);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FormController formController = Collect.getInstance().getFormController();
// https://github.com/getodk/collect/issues/998
if (formController == null) {
finish();
Timber.w("FormController is null");
return;
}
formEntryViewModel = new ViewModelProvider(this, formEntryViewModelFactory).get(FormEntryViewModel.class);
formEntryViewModel.formLoaded(Collect.getInstance().getFormController());
startIndex = formController.getFormIndex();
setTitle(formController.getFormTitle());
groupPathTextView = findViewById(R.id.pathtext);
jumpBeginningButton = findViewById(R.id.jumpBeginningButton);
jumpEndButton = findViewById(R.id.jumpEndButton);
configureButtons(formController);
restoreInstanceState(savedInstanceState);
refreshView();
// TODO: avoid another iteration through all displayed elements
if (recyclerView != null && recyclerView.getAdapter() != null && recyclerView.getAdapter().getItemCount() > 0) {
emptyView.setVisibility(View.GONE);
recyclerView.post(() -> {
int position = 0;
// startIndex which can either represent a question or a field list.
for (HierarchyElement hierarchyElement : elementsToDisplay) {
FormIndex indexToCheck = hierarchyElement.getFormIndex();
if (startIndex.equals(indexToCheck) || (formController.indexIsInFieldList(startIndex) && indexToCheck.toString().startsWith(startIndex.toString()))) {
position = elementsToDisplay.indexOf(hierarchyElement);
break;
}
}
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);
});
}
}
use of org.odk.collect.android.logic.HierarchyElement in project collect by opendatakit.
the class FormHierarchyActivity method refreshView.
/**
* @see #refreshView()
*/
private void refreshView(boolean isGoingUp) {
try {
FormController formController = Collect.getInstance().getFormController();
// Save the current index so we can return to the problematic question
// in the event of an error.
currentIndex = formController.getFormIndex();
elementsToDisplay = new ArrayList<>();
jumpToHierarchyStartIndex();
updateOptionsMenu();
int event = formController.getEvent();
if (event == FormEntryController.EVENT_BEGINNING_OF_FORM && !shouldShowRepeatGroupPicker()) {
// The beginning of form has no valid prompt to display.
groupPathTextView.setVisibility(View.GONE);
} else {
groupPathTextView.setVisibility(View.VISIBLE);
groupPathTextView.setText(getCurrentPath());
}
// Refresh the current event in case we did step forward.
event = formController.getEvent();
// Ref to the parent group that's currently being displayed.
//
// Because of the guard conditions below, we will skip
// everything until we exit this group.
TreeReference visibleGroupRef = null;
while (event != FormEntryController.EVENT_END_OF_FORM) {
// get the ref to this element
TreeReference currentRef = formController.getFormIndex().getReference();
// retrieve the current group
TreeReference curGroup = (visibleGroupRef == null) ? contextGroupRef : visibleGroupRef;
if (curGroup != null && !curGroup.isParentOf(currentRef, false)) {
// We have left the current group
if (visibleGroupRef == null) {
// We are done.
break;
} else {
// exit the inner group
visibleGroupRef = null;
}
}
if (visibleGroupRef != null) {
// We're in a 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:
{
// Nothing but repeat group instances should show up in the picker.
if (shouldShowRepeatGroupPicker()) {
break;
}
FormEntryPrompt fp = formController.getQuestionPrompt();
String label = fp.getShortText();
String answerDisplay = FormEntryPromptUtils.getAnswerText(fp, this, formController);
elementsToDisplay.add(new HierarchyElement(FormEntryPromptUtils.markQuestionIfIsRequired(label, fp.isRequired()), answerDisplay, null, HierarchyElement.Type.QUESTION, fp.getIndex()));
break;
}
case FormEntryController.EVENT_GROUP:
{
if (!formController.isGroupRelevant()) {
break;
}
// Nothing but repeat group instances should show up in the picker.
if (shouldShowRepeatGroupPicker()) {
break;
}
FormIndex index = formController.getFormIndex();
// Only display groups with a specific appearance attribute.
if (!formController.isDisplayableGroup(index)) {
break;
}
// Don't render other groups' children.
if (contextGroupRef != null && !contextGroupRef.isParentOf(currentRef, false)) {
break;
}
visibleGroupRef = currentRef;
FormEntryCaption caption = formController.getCaptionPrompt();
HierarchyElement groupElement = new HierarchyElement(caption.getShortText(), getString(R.string.group_label), ContextCompat.getDrawable(this, R.drawable.ic_folder_open), HierarchyElement.Type.VISIBLE_GROUP, caption.getIndex());
elementsToDisplay.add(groupElement);
// Skip to the next item outside the group.
event = formController.stepOverGroup();
continue;
}
case FormEntryController.EVENT_PROMPT_NEW_REPEAT:
{
// ignore it.
break;
}
case FormEntryController.EVENT_REPEAT:
{
boolean forPicker = shouldShowRepeatGroupPicker();
// Only break to exclude non-relevant repeat from picker
if (!formController.isGroupRelevant() && forPicker) {
break;
}
visibleGroupRef = currentRef;
// Don't render other groups' children.
if (contextGroupRef != null && !contextGroupRef.isParentOf(currentRef, false)) {
break;
}
FormEntryCaption fc = formController.getCaptionPrompt();
if (forPicker) {
// Don't render other groups' instances.
String repeatGroupPickerRef = repeatGroupPickerIndex.getReference().toString(false);
if (!currentRef.toString(false).equals(repeatGroupPickerRef)) {
break;
}
int itemNumber = fc.getMultiplicity() + 1;
// e.g. `friends > 1`
String repeatLabel = fc.getShortText() + " > " + itemNumber;
// If the child of the group has a more descriptive label, use that instead.
if (fc.getFormElement().getChildren().size() == 1 && fc.getFormElement().getChild(0) instanceof GroupDef) {
formController.stepToNextEvent(FormController.STEP_INTO_GROUP);
String itemLabel = formController.getCaptionPrompt().getShortText();
if (itemLabel != null) {
// e.g. `1. Alice`
repeatLabel = itemNumber + ".\u200E " + itemLabel;
}
}
HierarchyElement instance = new HierarchyElement(repeatLabel, null, null, HierarchyElement.Type.REPEAT_INSTANCE, fc.getIndex());
elementsToDisplay.add(instance);
} else if (fc.getMultiplicity() == 0) {
// Display the repeat header for the group.
HierarchyElement group = new HierarchyElement(fc.getShortText(), getString(R.string.repeatable_group_label), ContextCompat.getDrawable(this, R.drawable.ic_repeat), HierarchyElement.Type.REPEATABLE_GROUP, fc.getIndex());
elementsToDisplay.add(group);
}
break;
}
}
event = formController.stepToNextEvent(FormController.STEP_INTO_GROUP);
}
recyclerView.setAdapter(new HierarchyListAdapter(elementsToDisplay, this::onElementClick));
formController.jumpToIndex(currentIndex);
// that use presentation groups to display labels).
if (isDisplayingSingleGroup() && !screenIndex.isBeginningOfFormIndex()) {
if (isGoingUp) {
// Back out once more.
goUpLevel();
} else {
// Enter automatically.
formController.jumpToIndex(elementsToDisplay.get(0).getFormIndex());
refreshView();
}
}
} catch (Exception e) {
Timber.e(e);
createErrorDialog(e.getMessage());
}
}
use of org.odk.collect.android.logic.HierarchyElement 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());
}
}
Aggregations