package org.commcare.fragments; import android.app.Activity; import android.os.Bundle; import android.os.Parcelable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListAdapter; import android.widget.ListView; import org.commcare.CommCareApplication; import org.commcare.activities.EntitySelectActivity; import org.commcare.adapters.EntityDetailAdapter; import org.commcare.adapters.ListItemViewModifier; import org.commcare.cases.entity.Entity; import org.commcare.cases.entity.NodeEntityFactory; import org.commcare.dalvik.R; import org.commcare.interfaces.ModifiableEntityDetailAdapter; import org.commcare.models.AndroidSessionWrapper; import org.commcare.suite.model.Detail; import org.commcare.cases.entity.EntityUtil; import org.commcare.utils.DetailCalloutListener; import org.commcare.utils.SerializationUtil; import org.javarosa.core.model.condition.EvaluationContext; import org.javarosa.core.model.instance.TreeReference; /** * Fragment to display Detail content. Not meant for handling nested Detail objects. * * @author jschweers */ public class EntityDetailFragment extends Fragment { public static final String CHILD_DETAIL_INDEX = "edf_child_detail_index"; public static final String DETAIL_ID = "edf_detail_id"; public static final String DETAIL_INDEX = "edf_detail_index"; public static final String CHILD_REFERENCE = "edf_detail_reference"; protected ListItemViewModifier modifier; final AndroidSessionWrapper asw; ModifiableEntityDetailAdapter adapter; public EntityDetailFragment() { this.asw = CommCareApplication.instance().getCurrentSessionWrapper(); } public void setModifier(ListItemViewModifier modifier) { this.modifier = modifier; if (adapter != null) { adapter.setModifier(modifier); } } public static final String MODIFIER_KEY = "modifier"; @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (modifier instanceof Parcelable) { outState.putParcelable(MODIFIER_KEY, (Parcelable)modifier); } else { throw new IllegalArgumentException(modifier + " must implement Parcelable!"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (savedInstanceState != null) { this.modifier = savedInstanceState.getParcelable(MODIFIER_KEY); } // Note that some of this setup could be moved into onAttach if it would help performance Detail detailForDisplay = getDetailToUseForDisplay(); TreeReference referenceToDisplay = getReferenceToDisplay(); EvaluationContext contextForFactory = getFactoryContextForRef(referenceToDisplay); NodeEntityFactory factory = new NodeEntityFactory(detailForDisplay, contextForFactory); View rootView = inflater.inflate(R.layout.entity_detail_list, container, false); final Activity thisActivity = getActivity(); final Entity entity = factory.getEntity(referenceToDisplay); final DetailCalloutListener detailCalloutListener = thisActivity instanceof DetailCalloutListener ? ((DetailCalloutListener)thisActivity) : null; adapter = new EntityDetailAdapter( thisActivity, detailForDisplay, entity, detailCalloutListener, getArguments().getInt(DETAIL_INDEX), modifier ); ((ListView)rootView.findViewById(R.id.screen_entity_detail_list)).setAdapter((ListAdapter)adapter); return rootView; } protected EvaluationContext getFactoryContextForRef(TreeReference referenceToDisplay) { EvaluationContext context = EntityUtil.getEntityFactoryContext(referenceToDisplay, getArguments().getInt(CHILD_DETAIL_INDEX, -1) != -1, getParentDetail(), CommCareApplication.instance().getCurrentSessionWrapper().getEvaluationContext()); context.addFunctionHandler(EntitySelectActivity.getHereFunctionHandler()); return context; } /** * @return The Detail whose information will be displayed. If the root detail passed to this * fragment is NOT a compound detail, then this method will just return that detail. If it is * compound, then this will return one of its children (the one corresponding to the given * CHILD_DETAIL_INDEX) */ protected Detail getDetailToUseForDisplay() { Bundle args = getArguments(); final Detail detail = asw.getSession().getDetail(args.getString(DETAIL_ID)); final int childIndex = args.getInt(CHILD_DETAIL_INDEX, -1); final boolean rootDetailIsCompound = childIndex != -1; if (rootDetailIsCompound) { return detail.getDetails()[childIndex]; } return detail; } /** * @return Reference to the detail returned by getDetailToUseForDisplay */ protected TreeReference getReferenceToDisplay() { return SerializationUtil.deserializeFromBundle( getArguments(), CHILD_REFERENCE, TreeReference.class); } /** * @return Reference to this fragment's parent detail, which may be the same as this * fragment's detail. */ private Detail getParentDetail() { return asw.getSession().getDetail(getArguments().getString(DETAIL_ID)); } }