/*
* Copyright 2011 Jake Wharton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.actionbarsherlock.internal.app;
import java.util.HashMap;
import com.actionbarsherlock.internal.view.menu.MenuInflaterImpl;
import com.actionbarsherlock.internal.view.menu.MenuItemWrapper;
import com.actionbarsherlock.internal.view.menu.MenuWrapper;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v4.app.ActionBar;
import android.support.v4.view.ActionMode;
import android.support.v4.view.Menu;
import android.view.View;
import android.widget.SpinnerAdapter;
public final class ActionBarWrapper {
//No instances
private ActionBarWrapper() {}
/**
* Abstraction to get an instance of our implementing class.
*
* @param activity Parent activity.
* @return {@code ActionBar} instance.
*/
public static ActionBar createFor(Activity activity) {
if (!(activity instanceof SherlockActivity)) {
throw new RuntimeException("Activity must implement the SherlockActivity interface");
}
return new ActionBarWrapper.Impl(activity);
}
/**
* Handler for Android's native {@link android.app.ActionBar}.
*/
public static final class Impl extends ActionBar implements android.app.ActionBar.TabListener {
/** Mapping between support listeners and native listeners. */
private final HashMap<OnMenuVisibilityListener, android.app.ActionBar.OnMenuVisibilityListener> mMenuListenerMap = new HashMap<OnMenuVisibilityListener, android.app.ActionBar.OnMenuVisibilityListener>();
private final Activity mActivity;
private Impl(Activity activity) {
mActivity = activity;
}
/**
* Get the native {@link ActionBar} instance.
*
* @return The action bar.
*/
private android.app.ActionBar getActionBar() {
return mActivity.getActionBar();
}
/**
* Converts our Tab wrapper to a native version containing the wrapper
* instance as its tag.
*
* @param tab Tab wrapper instance.
* @return Native tab.
*/
private android.app.ActionBar.Tab convertTabToNative(ActionBar.Tab tab) {
return getActionBar().newTab()
.setCustomView(tab.getCustomView())
.setIcon(tab.getIcon())
.setTabListener(this)
.setTag(tab)
.setText(tab.getText());
}
@Override
public void onTabReselected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) {
ActionBar.TabListener listener = ((ActionBar.Tab)tab.getTag()).getTabListener();
if (listener != null) {
listener.onTabReselected((ActionBar.Tab)tab.getTag(), null);
}
}
@Override
public void onTabSelected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) {
ActionBar.TabListener listener = ((ActionBar.Tab)tab.getTag()).getTabListener();
if (listener != null) {
listener.onTabSelected((ActionBar.Tab)tab.getTag(), null);
}
}
@Override
public void onTabUnselected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) {
ActionBar.TabListener listener = ((ActionBar.Tab)tab.getTag()).getTabListener();
if (listener != null) {
listener.onTabUnselected((ActionBar.Tab)tab.getTag(), null);
}
}
// ---------------------------------------------------------------------
// ACTION MODE SUPPORT
// ---------------------------------------------------------------------
@Override
protected ActionMode startActionMode(final ActionMode.Callback callback) {
//We have to re-wrap the instances in every callback since the
//wrapped instance is needed before we could have a change to
//properly store it.
return new ActionModeWrapper(mActivity,
mActivity.startActionMode(new android.view.ActionMode.Callback() {
@Override
public boolean onPrepareActionMode(android.view.ActionMode mode, android.view.Menu menu) {
return callback.onPrepareActionMode(new ActionModeWrapper(mActivity, mode), new MenuWrapper(menu));
}
@Override
public void onDestroyActionMode(android.view.ActionMode mode) {
final ActionMode actionMode = new ActionModeWrapper(mActivity, mode);
callback.onDestroyActionMode(actionMode);
//Send the activity callback once the action mode callback has run.
//This type-check has already occurred in the action bar constructor.
((SherlockActivity)mActivity).onActionModeFinished(actionMode);
}
@Override
public boolean onCreateActionMode(android.view.ActionMode mode, android.view.Menu menu) {
return callback.onCreateActionMode(new ActionModeWrapper(mActivity, mode), new MenuWrapper(menu));
}
@Override
public boolean onActionItemClicked(android.view.ActionMode mode, android.view.MenuItem item) {
return callback.onActionItemClicked(new ActionModeWrapper(mActivity, mode), new MenuItemWrapper(item));
}
})
);
}
private static class ActionModeWrapper extends ActionMode {
private final Context mContext;
private final android.view.ActionMode mActionMode;
ActionModeWrapper(Context context, android.view.ActionMode actionMode) {
mContext = context;
mActionMode = actionMode;
}
@Override
public void finish() {
mActionMode.finish();
}
@Override
public View getCustomView() {
return mActionMode.getCustomView();
}
@Override
public Menu getMenu() {
return new MenuWrapper(mActionMode.getMenu());
}
@Override
public MenuInflaterImpl getMenuInflater() {
return new MenuInflaterImpl(mContext, null);
}
@Override
public CharSequence getSubtitle() {
return mActionMode.getSubtitle();
}
@Override
public CharSequence getTitle() {
return mActionMode.getTitle();
}
@Override
public void invalidate() {
mActionMode.invalidate();
}
@Override
public void setCustomView(View view) {
mActionMode.setCustomView(view);
}
@Override
public void setSubtitle(int resId) {
mActionMode.setSubtitle(resId);
}
@Override
public void setSubtitle(CharSequence subtitle) {
mActionMode.setSubtitle(subtitle);
}
@Override
public void setTitle(int resId) {
mActionMode.setTitle(resId);
}
@Override
public void setTitle(CharSequence title) {
mActionMode.setTitle(title);
}
}
// ---------------------------------------------------------------------
// ACTION BAR SUPPORT
// ---------------------------------------------------------------------
private static class TabImpl extends ActionBar.Tab {
final ActionBarWrapper.Impl mActionBar;
View mCustomView;
Drawable mIcon;
ActionBar.TabListener mListener;
Object mTag;
CharSequence mText;
TabImpl(ActionBarWrapper.Impl actionBar) {
mActionBar = actionBar;
}
@Override
public View getCustomView() {
return mCustomView;
}
@Override
public Drawable getIcon() {
return mIcon;
}
@Override
public int getPosition() {
final int tabCount = mActionBar.getTabCount();
for (int i = 0; i < tabCount; i++) {
if (mActionBar.getTabAt(i).equals(this)) {
return i;
}
}
return ActionBar.Tab.INVALID_POSITION;
}
@Override
public ActionBar.TabListener getTabListener() {
return mListener;
}
@Override
public Object getTag() {
return mTag;
}
@Override
public CharSequence getText() {
return mText;
}
@Override
public void select() {
mActionBar.selectTab(this);
}
@Override
public ActionBar.Tab setCustomView(int layoutResId) {
mCustomView = mActionBar.mActivity.getLayoutInflater().inflate(layoutResId, null);
return this;
}
@Override
public ActionBar.Tab setCustomView(View view) {
mCustomView = view;
return this;
}
@Override
public ActionBar.Tab setIcon(Drawable icon) {
mIcon = icon;
return this;
}
@Override
public ActionBar.Tab setIcon(int resId) {
mIcon = mActionBar.mActivity.getResources().getDrawable(resId);
return this;
}
@Override
public ActionBar.Tab setTabListener(TabListener listener) {
mListener = listener;
return this;
}
@Override
public ActionBar.Tab setTag(Object obj) {
mTag = obj;
return this;
}
@Override
public ActionBar.Tab setText(int resId) {
mText = mActionBar.mActivity.getResources().getString(resId);
return this;
}
@Override
public ActionBar.Tab setText(CharSequence text) {
mText = text;
return this;
}
}
@Override
public void addOnMenuVisibilityListener(final OnMenuVisibilityListener listener) {
if ((listener != null) && !mMenuListenerMap.containsKey(listener)) {
android.app.ActionBar.OnMenuVisibilityListener nativeListener = new android.app.ActionBar.OnMenuVisibilityListener() {
@Override
public void onMenuVisibilityChanged(boolean isVisible) {
listener.onMenuVisibilityChanged(isVisible);
}
};
mMenuListenerMap.put(listener, nativeListener);
getActionBar().addOnMenuVisibilityListener(nativeListener);
}
}
@Override
public void addTab(Tab tab) {
getActionBar().addTab(convertTabToNative(tab));
}
@Override
public void addTab(Tab tab, boolean setSelected) {
getActionBar().addTab(convertTabToNative(tab), setSelected);
}
@Override
public void addTab(Tab tab, int position) {
getActionBar().addTab(convertTabToNative(tab), position);
}
@Override
public void addTab(ActionBar.Tab tab, int position, boolean setSelected) {
getActionBar().addTab(convertTabToNative(tab), position, setSelected);
}
@Override
public View getCustomView() {
return getActionBar().getCustomView();
}
@Override
public int getDisplayOptions() {
return getActionBar().getDisplayOptions();
}
@Override
public int getHeight() {
return getActionBar().getHeight();
}
@Override
public int getNavigationItemCount() {
return getActionBar().getNavigationItemCount();
}
@Override
public int getNavigationMode() {
return getActionBar().getNavigationMode();
}
@Override
public int getSelectedNavigationIndex() {
return getActionBar().getSelectedNavigationIndex();
}
@Override
public Tab getSelectedTab() {
if (getActionBar().getSelectedTab() != null) {
return (ActionBar.Tab)getActionBar().getSelectedTab().getTag();
}
return null;
}
@Override
public CharSequence getSubtitle() {
return getActionBar().getSubtitle();
}
@Override
public ActionBar.Tab getTabAt(int index) {
if (getActionBar().getTabAt(index) != null) {
return (Tab)getActionBar().getTabAt(index).getTag();
}
return null;
}
@Override
public int getTabCount() {
return getActionBar().getTabCount();
}
@Override
public CharSequence getTitle() {
return getActionBar().getTitle();
}
@Override
public void hide() {
getActionBar().hide();
}
@Override
public boolean isShowing() {
return getActionBar().isShowing();
}
@Override
public ActionBar.Tab newTab() {
return new TabImpl(this);
}
@Override
public void removeAllTabs() {
getActionBar().removeAllTabs();
}
@Override
public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
if ((listener != null) && mMenuListenerMap.containsKey(listener)) {
getActionBar().removeOnMenuVisibilityListener(
mMenuListenerMap.remove(listener)
);
}
}
@Override
public void removeTab(Tab tab) {
final int tabCount = getActionBar().getTabCount();
for (int i = 0; i < tabCount; i++) {
if (getActionBar().getTabAt(i).getTag().equals(tab)) {
getActionBar().removeTabAt(i);
break;
}
}
}
@Override
public void removeTabAt(int position) {
getActionBar().removeTabAt(position);
}
@Override
public void selectTab(ActionBar.Tab tab) {
final int tabCount = getActionBar().getTabCount();
for (int i = 0; i < tabCount; i++) {
if (getActionBar().getTabAt(i).getTag().equals(tab)) {
getActionBar().setSelectedNavigationItem(i);
break;
}
}
}
@Override
public void setBackgroundDrawable(Drawable d) {
getActionBar().setBackgroundDrawable(d);
}
@Override
public void setCustomView(int resId) {
getActionBar().setCustomView(resId);
}
@Override
public void setCustomView(View view) {
getActionBar().setCustomView(view);
}
@Override
public void setCustomView(View view, LayoutParams layoutParams) {
android.app.ActionBar.LayoutParams nativeLayoutParams = new android.app.ActionBar.LayoutParams(layoutParams);
nativeLayoutParams.gravity = layoutParams.gravity;
getActionBar().setCustomView(view, nativeLayoutParams);
}
@Override
public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
getActionBar().setDisplayHomeAsUpEnabled(showHomeAsUp);
}
@Override
public void setDisplayOptions(int options, int mask) {
getActionBar().setDisplayOptions(options, mask);
}
@Override
public void setDisplayOptions(int options) {
getActionBar().setDisplayOptions(options);
}
@Override
public void setDisplayShowCustomEnabled(boolean showCustom) {
getActionBar().setDisplayShowCustomEnabled(showCustom);
}
@Override
public void setDisplayShowHomeEnabled(boolean showHome) {
getActionBar().setDisplayShowHomeEnabled(showHome);
}
@Override
public void setDisplayShowTitleEnabled(boolean showTitle) {
getActionBar().setDisplayShowTitleEnabled(showTitle);
}
@Override
public void setDisplayUseLogoEnabled(boolean useLogo) {
getActionBar().setDisplayUseLogoEnabled(useLogo);
}
@Override
public void setListNavigationCallbacks(SpinnerAdapter adapter, final OnNavigationListener callback) {
getActionBar().setListNavigationCallbacks(adapter, new android.app.ActionBar.OnNavigationListener() {
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
if (callback != null) {
return callback.onNavigationItemSelected(itemPosition, itemId);
}
return false;
}
});
}
@Override
public void setNavigationMode(int mode) {
getActionBar().setNavigationMode(mode);
}
@Override
public void setSelectedNavigationItem(int position) {
getActionBar().setSelectedNavigationItem(position);
}
@Override
public void setSubtitle(CharSequence subtitle) {
getActionBar().setSubtitle(subtitle);
}
@Override
public void setSubtitle(int resId) {
getActionBar().setSubtitle(resId);
}
@Override
public void setTitle(CharSequence title) {
getActionBar().setTitle(title);
}
@Override
public void setTitle(int resId) {
getActionBar().setTitle(resId);
}
@Override
public void show() {
getActionBar().show();
}
}
}