Skip to content

Commit

Permalink
Moved persistent case tile load to its own detail concept. Fixed issu…
Browse files Browse the repository at this point in the history
…es with lack of compartmentalization for incoming detail refs to allow mutliple refs in the same context.
  • Loading branch information
ctsims committed Nov 20, 2014
1 parent 80fdda8 commit a5b7f23
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package org.commcare.android.adapters;

import java.util.List;

import org.commcare.android.framework.EntityDetailFragment;
import org.commcare.android.models.Entity;
import org.commcare.android.util.DetailCalloutListener;
import org.commcare.android.util.SerializationUtil;
import org.commcare.suite.model.Detail;
import org.odk.collect.android.views.media.AudioController;
import org.javarosa.core.model.instance.TreeReference;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
Expand All @@ -23,12 +19,14 @@ public class EntityDetailPagerAdapter extends FragmentStatePagerAdapter {
Detail detail;
int detailIndex;
boolean hasDetailCalloutListener;
TreeReference mEntityReference;

public EntityDetailPagerAdapter(FragmentManager fm, Detail detail, int detailIndex, boolean hasDetailCalloutListener) {
public EntityDetailPagerAdapter(FragmentManager fm, Detail detail, int detailIndex, TreeReference reference, boolean hasDetailCalloutListener) {
super(fm);
this.detail = detail;
this.detailIndex = detailIndex;
this.hasDetailCalloutListener = hasDetailCalloutListener;
this.mEntityReference = reference;
}

/*
Expand All @@ -45,6 +43,7 @@ public Fragment getItem(int i) {
}
args.putInt(EntityDetailFragment.DETAIL_INDEX, detailIndex);
args.putBoolean(EntityDetailFragment.HAS_DETAIL_CALLOUT_LISTENER, hasDetailCalloutListener);
SerializationUtil.serializeToBundle(args, EntityDetailFragment.CHILD_REFERENCE, mEntityReference);
fragment.setArguments(args);
return fragment;
}
Expand Down
31 changes: 15 additions & 16 deletions app/src/org/commcare/android/framework/BreadcrumbBarFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.commcare.android.models.Entity;
import org.commcare.android.models.NodeEntityFactory;
import org.commcare.android.util.CommCareInstanceInitializer;
import org.commcare.android.util.SerializationUtil;
import org.commcare.android.util.SessionUnavailableException;
import org.commcare.android.view.GridEntityView;
import org.commcare.android.view.TabbedDetailView;
Expand All @@ -24,7 +25,6 @@
import android.app.ActionBar;
import android.app.ActionBar.LayoutParams;
import android.app.Activity;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
Expand Down Expand Up @@ -217,7 +217,8 @@ public boolean willChangeBounds() {

private View findAndLoadCaseTile(final Activity activity) {
final View holder = LayoutInflater.from(activity).inflate(R.layout.com_tile_holder, null);
View tile = this.loadTile(activity);
final Pair<View, TreeReference> tileData = this.loadTile(activity);
View tile = tileData == null ? null : tileData.first;
if(tile == null) { return null;}

final ImageButton openButton = ((ImageButton)holder.findViewById(R.id.com_tile_holder_btn_open));
Expand All @@ -244,7 +245,7 @@ public void onClick(View v) {
Detail detail = factory.getDetail();
mInternalDetailView.setDetail(detail);

mInternalDetailView.refresh(factory.getDetail(), 0, false);
mInternalDetailView.refresh(factory.getDetail(), tileData.second,0, false);
}
openButton.setVisibility(View.INVISIBLE);
expand(activity, holder.findViewById(R.id.com_tile_holder_detail_master));
Expand Down Expand Up @@ -272,7 +273,7 @@ public void run() {
}


private View loadTile(Activity activity) {
private Pair<View, TreeReference> loadTile(Activity activity) {
try {
AndroidSessionWrapper asw = CommCareApplication._().getCurrentSessionWrapper();
CommCareSession session = asw.getSession();
Expand All @@ -290,7 +291,7 @@ private View loadTile(Activity activity) {
}
}

View tile = buildContextTile(activity, stepToFrame, asw);
Pair<View, TreeReference> tile = buildContextTile(activity, stepToFrame, asw);
//some contexts may provide a tile that isn't really part of the current session's stack
if(tile == null && activity instanceof CommCareActivity) {
Pair<Detail, TreeReference> entityContext = ((CommCareActivity)activity).requestEntityContext();
Expand Down Expand Up @@ -574,35 +575,33 @@ public void onClick(View arg0) {

View tile;

private View buildContextTile(Activity activity, String[] stepToFrame, AndroidSessionWrapper asw) {
private Pair<View, TreeReference> buildContextTile(Activity activity, String[] stepToFrame, AndroidSessionWrapper asw) {
if(stepToFrame == null) { return null; }

//check to make sure we can look up this child
SessionDatum d = asw.getSession().findDatumDefinition(stepToFrame[1]);
if(d == null || d.getShortDetail() == null) { return null; }
if(d == null || d.getPersistentDetail() == null) { return null; }

//Make sure there is a valid reference to the entity we can build
Detail detail = asw.getSession().getDetail(d.getShortDetail());
Detail detail = asw.getSession().getDetail(d.getPersistentDetail());

EvaluationContext ec = asw.getEvaluationContext();

TreeReference ref = asw.getSession().getEntityFromID(ec, d, stepToFrame[2]);
if(ref == null) { return null; }

View v = buildContextTile(activity, detail, ref, asw);
v.setTag(d.getInlineDetail());
return v;
Pair<View, TreeReference> r = buildContextTile(activity, detail, ref, asw);
r.first.setTag(d.getInlineDetail());
return r;
}

private View buildContextTile(Activity activity, Detail detail, TreeReference ref, AndroidSessionWrapper asw) {
private Pair<View, TreeReference> buildContextTile(Activity activity, Detail detail, TreeReference ref, AndroidSessionWrapper asw) {
NodeEntityFactory nef = new NodeEntityFactory(detail, asw.getEvaluationContext());

CommCareApplication._().serializeToIntent(activity.getIntent(), EntityDetailActivity.CONTEXT_REFERENCE, ref);

Entity entity = nef.getEntity(ref);

GridEntityView tile = new GridEntityView(this.getActivity(), detail, entity, null);
return tile;
View tile = new GridEntityView(this.getActivity(), detail, entity, null);
return Pair.create(tile, ref);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import org.commcare.android.models.Entity;
import org.commcare.android.models.NodeEntityFactory;
import org.commcare.android.util.DetailCalloutListener;
import org.commcare.android.util.SerializationUtil;
import org.commcare.dalvik.R;
import org.commcare.dalvik.activities.EntityDetailActivity;
import org.commcare.dalvik.application.CommCareApplication;
import org.commcare.suite.model.Detail;
import org.javarosa.core.model.instance.TreeReference;
Expand All @@ -30,6 +30,7 @@ public class EntityDetailFragment extends Fragment {
public static final String DETAIL_ID = "edf_detail_id";
public static final String DETAIL_INDEX = "edf_detail_index";
public static final String HAS_DETAIL_CALLOUT_LISTENER = "edf_has_detail_callout_listener";
public static final String CHILD_REFERENCE = "edf_detail_reference";

private AndroidSessionWrapper asw;
private NodeEntityFactory factory;
Expand All @@ -56,8 +57,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
}

factory = new NodeEntityFactory(childDetail, asw.getEvaluationContext());
Entity entity = factory.getEntity(CommCareApplication._().deserializeFromIntent(
getActivity().getIntent(), EntityDetailActivity.CONTEXT_REFERENCE, TreeReference.class)
Entity entity = factory.getEntity(SerializationUtil.deserializeFromBundle(
args, CHILD_REFERENCE, TreeReference.class)
);

View rootView = inflater.inflate(R.layout.entity_detail_list, container, false);
Expand Down
75 changes: 75 additions & 0 deletions app/src/org/commcare/android/util/SerializationUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
*
*/
package org.commcare.android.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.commcare.android.database.DbUtil;
import org.commcare.dalvik.application.CommCareApplication;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.Externalizable;

import android.content.Intent;
import android.os.Bundle;

/**
* @author ctsims
*
*/
public class SerializationUtil {
public static byte[] serialize(Externalizable data) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
data.writeExternal(new DataOutputStream(baos));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return baos.toByteArray();
}

public static <T extends Externalizable> T deserialize(byte[] bytes, String name, Class<T> type) {
T t;
try {
t = type.newInstance();
t.readExternal(new DataInputStream(new ByteArrayInputStream(bytes)), DbUtil.getPrototypeFactory(CommCareApplication._()));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (DeserializationException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IllegalAccessException e1) {
e1.printStackTrace();
throw new RuntimeException(e1);
} catch (InstantiationException e1) {
e1.printStackTrace();
throw new RuntimeException(e1);
}
return t;
}


public static void serializeToIntent(Intent i, String name, Externalizable data) {
i.putExtra(name, serialize(data));
}

public static <T extends Externalizable> T deserializeFromIntent(Intent i, String name, Class<T> type) {
if(!i.hasExtra(name)) { return null;}
return deserialize(i.getByteArrayExtra(name), name, type);
}

public static void serializeToBundle(Bundle b, String name, Externalizable data) {
b.putByteArray(name, serialize(data));
}

public static <T extends Externalizable> T deserializeFromBundle(Bundle b, String name, Class<T> type) {
if(!b.containsKey(name)) { return null;}
return deserialize(b.getByteArray(name), name, type);
}
}
8 changes: 3 additions & 5 deletions app/src/org/commcare/android/view/TabbedDetailView.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.commcare.android.view;

import org.commcare.android.adapters.EntityDetailPagerAdapter;
import org.commcare.android.util.MediaUtil;
import org.commcare.dalvik.R;
import org.commcare.suite.model.Detail;
import org.commcare.suite.model.DisplayUnit;
import org.javarosa.core.model.instance.TreeReference;

import android.annotation.SuppressLint;
import android.content.Context;
Expand All @@ -16,10 +16,8 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
* Widget that combines a ViewPager with a set of page titles styled to look like tabs.
Expand Down Expand Up @@ -131,8 +129,8 @@ public void onClick(View v) {
/*
* Get form list from database and insert into view.
*/
public void refresh(Detail detail, int index, boolean hasDetailCalloutListener) {
mEntityDetailPagerAdapter = new EntityDetailPagerAdapter(mContext.getSupportFragmentManager(), detail, index, hasDetailCalloutListener);
public void refresh(Detail detail, TreeReference reference, int index, boolean hasDetailCalloutListener) {
mEntityDetailPagerAdapter = new EntityDetailPagerAdapter(mContext.getSupportFragmentManager(), detail, index, reference, hasDetailCalloutListener);
mViewPager.setAdapter(mEntityDetailPagerAdapter);
markSelectedTab(0);
}
Expand Down
18 changes: 10 additions & 8 deletions app/src/org/commcare/dalvik/activities/EntityDetailActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
import org.commcare.android.models.Entity;
import org.commcare.android.models.NodeEntityFactory;
import org.commcare.android.util.DetailCalloutListener;
import org.commcare.android.util.SerializationUtil;
import org.commcare.android.util.SessionUnavailableException;
import org.commcare.android.view.TabbedDetailView;
import org.commcare.dalvik.R;
import org.commcare.dalvik.application.CommCareApplication;
import org.commcare.suite.model.Detail;
import org.commcare.suite.model.Entry;
import org.commcare.suite.model.SessionDatum;
import org.commcare.util.CommCareSession;
import org.commcare.util.SessionFrame;
import org.javarosa.core.model.instance.TreeReference;
Expand Down Expand Up @@ -45,14 +45,16 @@ public class EntityDetailActivity extends CommCareActivity implements DetailCall
public static final String IS_DEAD_END = "eda_ide";
public static final String CONTEXT_REFERENCE = "eda_crid";
public static final String DETAIL_ID = "eda_detail_id";
public static final String DETAIL_SHORT_ID = "eda_short_id";
public static final String DETAIL_PERSISTENT_ID = "eda_persistent_id";

Entry prototype;
Entity<TreeReference> entity;
EntityDetailAdapter adapter;
NodeEntityFactory factory;
Pair<Detail, TreeReference> mEntityContext;

TreeReference mTreeReference;

private int detailIndex;

@UiElement(value=R.id.entity_detail)
Expand Down Expand Up @@ -81,14 +83,14 @@ public void onCreate(Bundle savedInstanceState) {

factory = new NodeEntityFactory(session.getDetail(getIntent().getStringExtra(EntityDetailActivity.DETAIL_ID)), asw.getEvaluationContext());

TreeReference ref = CommCareApplication._().deserializeFromIntent(getIntent(), EntityDetailActivity.CONTEXT_REFERENCE, TreeReference.class);
String shortDetailId = getIntent().getStringExtra(EntityDetailActivity.DETAIL_SHORT_ID);
mTreeReference = SerializationUtil.deserializeFromIntent(getIntent(), EntityDetailActivity.CONTEXT_REFERENCE, TreeReference.class);
String shortDetailId = getIntent().getStringExtra(EntityDetailActivity.DETAIL_PERSISTENT_ID);
if(shortDetailId != null) {
Detail shortDetail = session.getDetail(shortDetailId);
this.mEntityContext = new Pair<Detail, TreeReference>(shortDetail, ref);
this.mEntityContext = new Pair<Detail, TreeReference>(shortDetail, mTreeReference);
}

entity = factory.getEntity(ref);
entity = factory.getEntity(mTreeReference);

super.onCreate(savedInstanceState);

Expand Down Expand Up @@ -128,7 +130,7 @@ public void onClick(View v) {
}

mDetailView.setRoot((ViewGroup) container.findViewById(R.id.entity_detail_tabs));
mDetailView.refresh(factory.getDetail(), detailIndex, true);
mDetailView.refresh(factory.getDetail(), mTreeReference, detailIndex, true);
} catch(SessionUnavailableException sue) {
//TODO: Login and return to try again
}
Expand Down Expand Up @@ -183,7 +185,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent intent)
switch(requestCode) {
case CALL_OUT:
if(resultCode == RESULT_CANCELED) {
mDetailView.refresh(factory.getDetail(), detailIndex, true);
mDetailView.refresh(factory.getDetail(), mTreeReference, detailIndex, true);
return;
} else {
long duration = intent.getLongExtra(CallOutActivity.CALL_DURATION, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.commcare.android.models.Entity;
import org.commcare.android.models.NodeEntityFactory;
import org.commcare.android.util.CommCareInstanceInitializer;
import org.commcare.android.util.SerializationUtil;
import org.commcare.dalvik.R;
import org.commcare.dalvik.application.CommCareApplication;
import org.commcare.dalvik.geo.EntityOverlay;
Expand Down Expand Up @@ -133,7 +134,7 @@ protected void onCreate(Bundle icicle) {
@Override
protected void selected(TreeReference ref) {
Intent i = new Intent(EntityMapActivity.this.getIntent());
CommCareApplication._().serializeToIntent(i, EntityDetailActivity.CONTEXT_REFERENCE, ref);
SerializationUtil.serializeToIntent(i, EntityDetailActivity.CONTEXT_REFERENCE, ref);

setResult(RESULT_OK, i);

Expand Down

0 comments on commit a5b7f23

Please sign in to comment.