package oraculum.droid.ui;
import java.util.List;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
/**
* A {@link BaseActivity} that can contain multiple panes, and has the ability to substitute
* fragments for activities when intents are fired using
* {@link BaseActivity#openActivityOrFragment(android.content.Intent)}.
*/
public abstract class BaseMultiPaneActivity extends BaseActivity {
/** {@inheritDoc} */
@Override
public void openActivityOrFragment(final Intent intent) {
final PackageManager pm = getPackageManager();
List<ResolveInfo> resolveInfoList = pm
.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resolveInfoList) {
final FragmentReplaceInfo fri = onSubstituteFragmentForActivityLaunch(
resolveInfo.activityInfo.name);
if (fri != null) {
final Bundle arguments = intentToFragmentArguments(intent);
final FragmentManager fm = getSupportFragmentManager();
try {
Fragment fragment = (Fragment) fri.getFragmentClass().newInstance();
fragment.setArguments(arguments);
FragmentTransaction ft = fm.beginTransaction();
ft.replace(fri.getContainerId(), fragment, fri.getFragmentTag());
onBeforeCommitReplaceFragment(fm, ft, fragment);
ft.commit();
} catch (InstantiationException e) {
throw new IllegalStateException(
"Error creating new fragment.", e);
} catch (IllegalAccessException e) {
throw new IllegalStateException(
"Error creating new fragment.", e);
}
return;
}
}
super.openActivityOrFragment(intent);
}
/**
* Callback that's triggered to find out if a fragment can substitute the given activity class.
* Base activites should return a {@link FragmentReplaceInfo} if a fragment can act in place
* of the given activity class name.
*/
protected FragmentReplaceInfo onSubstituteFragmentForActivityLaunch(String activityClassName) {
return null;
}
/**
* Called just before a fragment replacement transaction is committed in response to an intent
* being fired and substituted for a fragment.
*/
protected void onBeforeCommitReplaceFragment(FragmentManager fm, FragmentTransaction ft,
Fragment fragment) {
}
/**
* A class describing information for a fragment-substitution, used when a fragment can act
* in place of an activity.
*/
protected class FragmentReplaceInfo {
@SuppressWarnings("rawtypes")
private Class mFragmentClass;
private String mFragmentTag;
private int mContainerId;
@SuppressWarnings("rawtypes")
public FragmentReplaceInfo(Class fragmentClass, String fragmentTag, int containerId) {
mFragmentClass = fragmentClass;
mFragmentTag = fragmentTag;
mContainerId = containerId;
}
@SuppressWarnings("rawtypes")
public Class getFragmentClass() {
return mFragmentClass;
}
public String getFragmentTag() {
return mFragmentTag;
}
public int getContainerId() {
return mContainerId;
}
}
}