package android.support.v4.app;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.holoeverywhere.HoloEverywhere;
import org.holoeverywhere.HoloEverywhere.PreferenceImpl;
import org.holoeverywhere.IHoloActivity;
import org.holoeverywhere.LayoutInflater;
import org.holoeverywhere.SystemServiceManager;
import org.holoeverywhere.ThemeManager;
import org.holoeverywhere.app.Activity;
import org.holoeverywhere.app.Application;
import org.holoeverywhere.app.ContextThemeWrapperPlus;
import org.holoeverywhere.internal.WindowDecorView;
import org.holoeverywhere.preference.PreferenceManagerHelper;
import org.holoeverywhere.preference.SharedPreferences;
import org.holoeverywhere.util.SparseIntArray;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources.Theme;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import com.actionbarsherlock.internal.view.menu.ContextMenuBackWrapper;
import com.actionbarsherlock.internal.view.menu.ContextMenuCallbackGetter;
import com.actionbarsherlock.internal.view.menu.ContextMenuDecorView.ContextMenuListenersProvider;
import com.actionbarsherlock.internal.view.menu.ContextMenuItemWrapper;
import com.actionbarsherlock.internal.view.menu.ContextMenuListener;
import com.actionbarsherlock.internal.view.menu.ContextMenuWrapper;
import com.actionbarsherlock.view.ContextMenu;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
public abstract class _HoloActivity extends Watson implements IHoloActivity,
ContextMenuListenersProvider {
public static class Holo implements Parcelable {
public static final Parcelable.Creator<Holo> CREATOR = new Creator<Holo>() {
@Override
public Holo createFromParcel(Parcel source) {
try {
@SuppressWarnings("unchecked")
Class<? extends Holo> clazz = (Class<? extends Holo>) Class.forName(source
.readString());
Holo holo = clazz.newInstance();
holo.createFromParcel(source);
return holo;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public Holo[] newArray(int size) {
return new Holo[size];
}
};
public static Holo defaultConfig() {
return new Holo();
}
public boolean applyImmediately = false;
public boolean forceThemeApply = false;
public boolean ignoreApplicationInstanceCheck = false;
public boolean ignoreThemeCheck = false;
public boolean requireRoboguice = false;
public boolean requireSherlock = true;
public boolean requireSlider = false;
private SparseIntArray windowFeatures;
protected Holo copy(Holo holo) {
forceThemeApply = holo.forceThemeApply;
ignoreThemeCheck = holo.ignoreThemeCheck;
ignoreApplicationInstanceCheck = holo.ignoreApplicationInstanceCheck;
requireSherlock = holo.requireSherlock;
requireSlider = holo.requireSlider;
requireRoboguice = holo.requireRoboguice;
applyImmediately = holo.applyImmediately;
windowFeatures = holo.windowFeatures == null ? null : holo.windowFeatures.clone();
return this;
}
protected void createFromParcel(Parcel source) {
forceThemeApply = source.readInt() == 1;
ignoreThemeCheck = source.readInt() == 1;
ignoreApplicationInstanceCheck = source.readInt() == 1;
requireSherlock = source.readInt() == 1;
requireSlider = source.readInt() == 1;
requireRoboguice = source.readInt() == 1;
applyImmediately = source.readInt() == 1;
windowFeatures = source.readParcelable(SparseIntArray.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
public void requestWindowFeature(int feature) {
if (windowFeatures == null) {
windowFeatures = new SparseIntArray();
}
windowFeatures.put(feature, 1);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getClass().getName());
dest.writeInt(forceThemeApply ? 1 : 0);
dest.writeInt(ignoreThemeCheck ? 1 : 0);
dest.writeInt(ignoreApplicationInstanceCheck ? 1 : 0);
dest.writeInt(requireSherlock ? 1 : 0);
dest.writeInt(requireSlider ? 1 : 0);
dest.writeInt(requireRoboguice ? 1 : 0);
dest.writeInt(applyImmediately ? 1 : 0);
dest.writeParcelable(windowFeatures, flags);
}
}
private static final class HoloThemeException extends RuntimeException {
private static final long serialVersionUID = -2346897999325868420L;
public HoloThemeException(_HoloActivity activity) {
super("You must apply Holo.Theme, Holo.Theme.Light or "
+ "Holo.Theme.Light.DarkActionBar theme on the activity ("
+ activity.getClass().getSimpleName()
+ ") for using HoloEverywhere");
}
}
private static final String CONFIG_KEY = "holo:config:activity";
private Context mActionBarContext;
private Holo mConfig;
private Map<View, ContextMenuListener> mContextMenuListeners;
private boolean mForceThemeApply = false;
private boolean mInited = false;
private int mLastThemeResourceId = 0;
private MenuInflater mMenuInflater;
private final List<WeakReference<OnWindowFocusChangeListener>> mOnWindowFocusChangeListeners = new ArrayList<WeakReference<OnWindowFocusChangeListener>>();
private final String TAG = getClass().getSimpleName();
@Override
public void addContentView(View view, LayoutParams params) {
super.addContentView(prepareDecorView(view), params);
}
@Override
public void addOnWindowFocusChangeListener(OnWindowFocusChangeListener listener) {
synchronized (mOnWindowFocusChangeListeners) {
Iterator<WeakReference<OnWindowFocusChangeListener>> i = mOnWindowFocusChangeListeners
.iterator();
while (i.hasNext()) {
WeakReference<OnWindowFocusChangeListener> reference = i.next();
if (reference == null) {
i.remove();
continue;
}
OnWindowFocusChangeListener iListener = reference.get();
if (iListener == null) {
i.remove();
continue;
}
if (iListener == listener) {
return;
}
}
mOnWindowFocusChangeListeners
.add(new WeakReference<OnWindowFocusChangeListener>(listener));
}
}
protected Holo createConfig(Bundle savedInstanceState) {
if (mConfig == null) {
mConfig = onCreateConfig(savedInstanceState);
}
if (mConfig == null) {
mConfig = Holo.defaultConfig();
}
return mConfig;
}
protected void forceInit(Bundle savedInstanceState) {
if (mInited) {
return;
}
if (mConfig == null && savedInstanceState != null
&& savedInstanceState.containsKey(CONFIG_KEY)) {
mConfig = savedInstanceState.getParcelable(CONFIG_KEY);
}
onInit(mConfig, savedInstanceState);
}
public Holo getConfig() {
return mConfig;
}
@Override
public ContextMenuListener getContextMenuListener(View view) {
if (mContextMenuListeners == null) {
return null;
}
return mContextMenuListeners.get(view);
}
@Override
public SharedPreferences getDefaultSharedPreferences() {
return PreferenceManagerHelper.getDefaultSharedPreferences(this);
}
@Override
public SharedPreferences getDefaultSharedPreferences(PreferenceImpl impl) {
return PreferenceManagerHelper.getDefaultSharedPreferences(this, impl);
}
public int getLastThemeResourceId() {
return mLastThemeResourceId;
}
@Override
public LayoutInflater getLayoutInflater() {
return LayoutInflater.from(this);
}
@Override
public SharedPreferences getSharedPreferences(PreferenceImpl impl,
String name, int mode) {
return PreferenceManagerHelper.wrap(this, impl, name, mode);
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
return PreferenceManagerHelper.wrap(this, name, mode);
}
/**
* @return Themed context for using in action bar
*/
public Context getSupportActionBarContext() {
if (mActionBarContext == null) {
int theme = ThemeManager.getThemeType(this);
if (theme != ThemeManager.LIGHT) {
theme = ThemeManager.DARK;
}
theme = ThemeManager.getThemeResource(theme, false);
if (mLastThemeResourceId == theme) {
mActionBarContext = this;
} else {
mActionBarContext = new ContextThemeWrapperPlus(this, theme);
}
}
return mActionBarContext;
}
@Override
public Application getSupportApplication() {
return Application.getLastInstance();
}
@Override
public MenuInflater getSupportMenuInflater() {
if (mMenuInflater != null) {
return mMenuInflater;
}
mMenuInflater = new MenuInflater(getSupportActionBarContext(), this);
return mMenuInflater;
}
@Override
public Object getSystemService(String name) {
return SystemServiceManager.getSystemService(this, name);
}
@Override
public Theme getTheme() {
if (mLastThemeResourceId == 0) {
setTheme(ThemeManager.getDefaultTheme());
}
return super.getTheme();
}
protected void init(Holo config) {
init(config, null);
}
protected void init(Holo config, Bundle savedInstanceState) {
mConfig = config;
if (mConfig.applyImmediately) {
onInit(mConfig, savedInstanceState);
}
}
@Override
public void invalidateOptionsMenu() {
supportInvalidateOptionsMenu();
}
@Override
public boolean isForceThemeApply() {
return mForceThemeApply;
}
public boolean isInited() {
return mInited;
}
@Override
@SuppressLint("NewApi")
public void onBackPressed() {
if (!getSupportFragmentManager().popBackStackImmediate()) {
finish();
}
}
@Override
public final boolean onContextItemSelected(android.view.MenuItem item) {
return onContextItemSelected(new ContextMenuItemWrapper(item));
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if (item instanceof ContextMenuItemWrapper) {
return super.onContextItemSelected(((ContextMenuItemWrapper) item)
.unwrap());
}
return false;
}
@Override
public final void onContextMenuClosed(android.view.Menu menu) {
if (menu instanceof android.view.ContextMenu) {
onContextMenuClosed(new ContextMenuWrapper(
(android.view.ContextMenu) menu));
} else {
Log.w(TAG, "onContextMenuClosed: menu is not ContextMenu instance");
super.onContextMenuClosed(menu);
}
}
@Override
public void onContextMenuClosed(ContextMenu menu) {
if (menu instanceof ContextMenuWrapper) {
super.onContextMenuClosed(((ContextMenuWrapper) menu).unwrap());
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
forceInit(savedInstanceState);
super.onCreate(savedInstanceState);
}
protected Holo onCreateConfig(Bundle savedInstanceState) {
if (savedInstanceState != null && savedInstanceState.containsKey(CONFIG_KEY)) {
final Holo config = savedInstanceState.getParcelable(CONFIG_KEY);
if (config != null) {
return config;
}
}
return Holo.defaultConfig();
}
@Override
public final void onCreateContextMenu(android.view.ContextMenu menu,
View v, ContextMenuInfo menuInfo) {
onCreateContextMenu(new ContextMenuWrapper(menu), v, menuInfo);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view,
ContextMenuInfo menuInfo) {
final android.view.ContextMenu nativeMenu;
if (menu instanceof ContextMenuWrapper) {
nativeMenu = ((ContextMenuWrapper) menu).unwrap();
} else {
nativeMenu = new ContextMenuBackWrapper(menu);
}
super.onCreateContextMenu(nativeMenu, view, menuInfo);
if (view instanceof ContextMenuCallbackGetter) {
final OnCreateContextMenuListener l = ((ContextMenuCallbackGetter) view)
.getOnCreateContextMenuListener();
if (l != null) {
l.onCreateContextMenu(nativeMenu, view, menuInfo);
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return false;
}
@Override
protected void onDestroy() {
super.onDestroy();
LayoutInflater.removeInstance(this);
}
/**
* Do not override this method. Use {@link #onPreInit(Holo, Bundle)} and
* {@link #onPostInit(Holo, Bundle)}
*/
protected void onInit(Holo config, Bundle savedInstanceState) {
if (mInited) {
throw new IllegalStateException("This instance was already inited");
}
mInited = true;
if (config == null) {
config = createConfig(savedInstanceState);
}
if (config == null) {
config = Holo.defaultConfig();
}
onPreInit(config, savedInstanceState);
if (!config.ignoreApplicationInstanceCheck && !(getApplication() instanceof Application)) {
throw new IllegalStateException(
"Application instance isn't HoloEverywhere.\n" +
"Put attr 'android:name=\"org.holoeverywhere.app.Application\"'" +
" in <application> tag of AndroidManifest.xml");
}
getLayoutInflater().setFragmentActivity(this);
if (this instanceof Activity) {
Activity activity = (Activity) this;
if (config.requireRoboguice) {
activity.addon(Activity.ADDON_ROBOGUICE);
}
if (config.requireSlider) {
activity.addon(Activity.ADDON_SLIDER);
}
if (config.requireSherlock) {
activity.addonSherlock();
}
final SparseIntArray windowFeatures = config.windowFeatures;
if (windowFeatures != null) {
for (int i = 0; i < windowFeatures.size(); i++) {
if (windowFeatures.valueAt(i) > 0) {
requestWindowFeature((long) windowFeatures.keyAt(i));
}
}
}
boolean forceThemeApply = isForceThemeApply();
if (config.forceThemeApply) {
setForceThemeApply(forceThemeApply = true);
}
if (mLastThemeResourceId == 0) {
forceThemeApply = true;
}
ThemeManager.applyTheme(activity, forceThemeApply);
if (!config.ignoreThemeCheck && ThemeManager.getThemeType(this) == ThemeManager.INVALID) {
throw new HoloThemeException(activity);
}
}
onPostInit(config, savedInstanceState);
lockAttaching();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return false;
}
protected void onPostInit(Holo config, Bundle savedInstanceState) {
}
protected void onPreInit(Holo config, Bundle savedInstanceState) {
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
return false;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mConfig != null) {
outState.putParcelable(CONFIG_KEY, mConfig);
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
synchronized (mOnWindowFocusChangeListeners) {
Iterator<WeakReference<OnWindowFocusChangeListener>> i = mOnWindowFocusChangeListeners
.iterator();
while (i.hasNext()) {
WeakReference<OnWindowFocusChangeListener> reference = i.next();
if (reference == null) {
i.remove();
continue;
}
OnWindowFocusChangeListener iListener = reference.get();
if (iListener == null) {
i.remove();
continue;
}
iListener.onWindowFocusChanged(hasFocus);
}
}
}
@Override
public View prepareDecorView(View view) {
return prepareDecorView(view, null);
}
public View prepareDecorView(View v, ViewGroup.LayoutParams params) {
if (v instanceof WindowDecorView) {
((WindowDecorView) v).setProvider(this);
return v;
}
WindowDecorView decor = new WindowDecorView(this, v, params);
decor.setProvider(this);
return decor;
}
@Override
public void registerForContextMenu(View view) {
if (HoloEverywhere.WRAP_TO_NATIVE_CONTEXT_MENU) {
super.registerForContextMenu(view);
} else {
registerForContextMenu(view, this);
}
}
public void registerForContextMenu(View view, ContextMenuListener listener) {
if (mContextMenuListeners == null) {
mContextMenuListeners = new WeakHashMap<View, ContextMenuListener>();
}
mContextMenuListeners.put(view, listener);
}
@Override
public void requestWindowFeature(long featureId) {
if (!mInited) {
createConfig(null).requestWindowFeature((int) featureId);
}
}
public void setForceThemeApply(boolean forceThemeApply) {
mForceThemeApply = forceThemeApply;
}
@Override
public void setTheme(int resid) {
setTheme(resid, true);
}
public synchronized void setTheme(int resid, boolean modifyGlobal) {
if (resid > ThemeManager._START_RESOURCES_ID) {
if (mLastThemeResourceId != resid) {
mActionBarContext = null;
mMenuInflater = null;
super.setTheme(mLastThemeResourceId = resid);
}
} else {
if ((resid & ThemeManager.COLOR_SCHEME_MASK) == 0) {
int theme = ThemeManager.getTheme(getIntent(), false)
& ThemeManager.COLOR_SCHEME_MASK;
if (theme == 0) {
theme = ThemeManager.getTheme(getParentActivityIntent(), false)
& ThemeManager.COLOR_SCHEME_MASK;
}
if (theme != 0) {
resid |= theme & ThemeManager.COLOR_SCHEME_MASK;
}
}
setTheme(ThemeManager.getThemeResource(resid, modifyGlobal));
}
}
@Override
public void startActivities(Intent[] intents) {
startActivities(intents, null);
}
@Override
public void startActivities(Intent[] intents, Bundle options) {
for (Intent intent : intents) {
startActivity(intent, options);
}
}
@Override
public void startActivity(Intent intent) {
startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, Bundle options) {
startActivityForResult(intent, -1, options);
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
@Override
public void startActivityForResult(Intent intent, int requestCode,
Bundle options) {
if (HoloEverywhere.ALWAYS_USE_PARENT_THEME) {
ThemeManager.startActivity(this, intent, requestCode, options);
} else {
superStartActivity(intent, requestCode, options);
}
}
@Override
public android.content.SharedPreferences superGetSharedPreferences(
String name, int mode) {
return super.getSharedPreferences(name, mode);
}
@Override
public Object superGetSystemService(String name) {
return super.getSystemService(name);
}
@Override
@SuppressLint("NewApi")
public void superStartActivity(Intent intent, int requestCode,
Bundle options) {
if (VERSION.SDK_INT >= 16) {
super.startActivityForResult(intent, requestCode, options);
} else {
super.startActivityForResult(intent, requestCode);
}
}
@Override
public void supportInvalidateOptionsMenu() {
if (VERSION.SDK_INT >= 11) {
super.invalidateOptionsMenu();
}
}
@Override
public void unregisterForContextMenu(View view) {
if (HoloEverywhere.WRAP_TO_NATIVE_CONTEXT_MENU) {
super.unregisterForContextMenu(view);
} else {
if (mContextMenuListeners != null) {
mContextMenuListeners.remove(view);
}
}
}
}