From 92f8a567fb47496df3a6b3f4a68b5359b0371fd2 Mon Sep 17 00:00:00 2001 From: Owen Lin Date: Tue, 17 Jul 2012 16:50:31 +0800 Subject: Add SimpleMenuXXX implementation for the Gingerbread platform. 1. Add a SimpleMenuInflator to parse the res/menu/xxx.xml files. 2. Add minimal code to show the menu. **NOTE** This change is going to be replaced by the ActionBar compat library when it gets ready and integrated. The purpose of this change is making Gallery/Camera run on GB. Change-Id: Ia7d402c82a6da1b9558ebbd103e161d2471b34dd --- .../com/android/gallery3d/common/ApiHelper.java | 5 +- .../gallery3d/actionbar/ActionBarUtils.java | 10 +- .../gallery3d/actionbar/SimpleActionBar.java | 136 +++++++++++++++++++++ .../gallery3d/actionbar/SimpleActionBarView.java | 54 ++++++++ .../gallery3d/actionbar/SimpleActionMode.java | 44 +++++++ .../android/gallery3d/actionbar/SimpleMenu.java | 87 +++++++++++++ .../gallery3d/actionbar/SimpleMenuInflater.java | 132 ++++++++++++++++++++ .../actionbar/SystemActionModeWrapper.java | 6 +- src/com/android/gallery3d/app/ActivityState.java | 4 +- src/com/android/gallery3d/ui/PopupList.java | 22 +++- 10 files changed, 491 insertions(+), 9 deletions(-) create mode 100644 src/com/android/gallery3d/actionbar/SimpleActionBar.java create mode 100644 src/com/android/gallery3d/actionbar/SimpleActionBarView.java create mode 100644 src/com/android/gallery3d/actionbar/SimpleActionMode.java create mode 100644 src/com/android/gallery3d/actionbar/SimpleMenu.java create mode 100644 src/com/android/gallery3d/actionbar/SimpleMenuInflater.java diff --git a/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java b/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java index 9beac8807..406c5263c 100644 --- a/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java +++ b/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java @@ -163,10 +163,13 @@ public class ApiHelper { public static final boolean HAS_SURFACE_TEXTURE_RECORDING = Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; - + public static final boolean HAS_MENU_ITEM_SHOW_AS_ACTION = Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + public static final boolean HAS_ACTION_BAR = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + private static boolean hasField(Class klass, String fieldName) { try { klass.getDeclaredField(fieldName); diff --git a/src/com/android/gallery3d/actionbar/ActionBarUtils.java b/src/com/android/gallery3d/actionbar/ActionBarUtils.java index 22a3f9c9c..25ccb92b3 100644 --- a/src/com/android/gallery3d/actionbar/ActionBarUtils.java +++ b/src/com/android/gallery3d/actionbar/ActionBarUtils.java @@ -18,14 +18,20 @@ package com.android.gallery3d.actionbar; import android.app.Activity; +import com.android.gallery3d.common.ApiHelper; + public class ActionBarUtils { public static ActionBarInterface getActionBar(Activity activity) { - return new SystemActionBarWrapper(activity); + return ApiHelper.HAS_ACTION_BAR + ? new SystemActionBarWrapper(activity) + : new SimpleActionBar(activity); } public static ActionModeInterface startActionMode( Activity activity, ActionModeInterface.Callback callback) { - return new SystemActionModeWrapper(activity, callback); + return ApiHelper.HAS_ACTION_BAR + ? new SystemActionModeWrapper(activity, callback) + : new SimpleActionMode(); } } diff --git a/src/com/android/gallery3d/actionbar/SimpleActionBar.java b/src/com/android/gallery3d/actionbar/SimpleActionBar.java new file mode 100644 index 000000000..8d709a946 --- /dev/null +++ b/src/com/android/gallery3d/actionbar/SimpleActionBar.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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.android.gallery3d.actionbar; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.Menu; +import android.view.ViewGroup.LayoutParams; +import android.widget.FrameLayout; +import android.widget.SpinnerAdapter; + +import com.android.gallery3d.R; + +public class SimpleActionBar implements ActionBarInterface { + private final FrameLayout mHeaderView; + private final SimpleActionBarView mActionBar; + private final SimpleMenu mOptionsMenu = new SimpleMenu(); + private final Context mContext; + + public SimpleActionBar(Activity activity) { + mContext = activity; + mHeaderView = (FrameLayout) activity.findViewById(R.id.header); + mActionBar = new SimpleActionBarView(activity, null); + + if (mHeaderView != null) { + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + + // Unhide the next line to show the menu button + // mHeaderView.setVisibility(View.VISIBLE); + mHeaderView.addView(mActionBar, params); + } + } + + @Override + public void setMenuItemVisible(int menuItemId, boolean visible) { + mOptionsMenu.setMenuItemVisible(menuItemId, visible); + } + + @Override + public void setMenuItemTitle(int menuItemId, String title) { + mOptionsMenu.setMenuItemTitle(menuItemId, title); + } + + @Override + public void setMenuItemIntent(int menuItemId, Intent intent) { + mOptionsMenu.setMenuItemIntent(menuItemId, intent); + } + + @Override + public int getHeight() { + return mActionBar.getHeight(); + } + + @Override + public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener listener) { + } + + @Override + public void setNavigationMode(int mode) { + } + + @Override + public void setSelectedNavigationItem(int index) { + } + + @Override + public void addOnMenuVisibilityListener(OnMenuVisibilityListener l) { + } + + @Override + public void removeOnMenuVisibilityListener(OnMenuVisibilityListener l) { + } + + @Override + public void setDisplayOptions(int options, int mask) { + } + + @Override + public void setHomeButtonEnabled(boolean enabled) { + } + + @Override + public void setTitle(String title) { + } + + @Override + public void setSubtitle(String subtitle) { + } + + @Override + public void show() { + } + + @Override + public void hide() { + } + + @Override + public void setShareIntent(Intent intent) { + } + + @Override + public void setLogo(Drawable logo) { + } + + @Override + public boolean createActionMenu(Menu menu, int menuResId) { + SimpleMenuInflater inflater = new SimpleMenuInflater(mContext); + mOptionsMenu.clear(); + inflater.inflate(mOptionsMenu, menuResId); + mActionBar.setOptionsMenu(mOptionsMenu); + return false; + } + + @Override + public boolean hasShareMenuItem() { + return false; + } +} diff --git a/src/com/android/gallery3d/actionbar/SimpleActionBarView.java b/src/com/android/gallery3d/actionbar/SimpleActionBarView.java new file mode 100644 index 000000000..94ba56b0b --- /dev/null +++ b/src/com/android/gallery3d/actionbar/SimpleActionBarView.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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.android.gallery3d.actionbar; +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; + +import com.android.gallery3d.R; +import com.android.gallery3d.ui.PopupList; + + +public class SimpleActionBarView extends LinearLayout { + + private PopupList mPopupList; + + public SimpleActionBarView(Context context, AttributeSet attrs) { + super(context, attrs); + LayoutInflater.from(context).inflate(R.layout.simple_action_bar, this); + Button button = (Button) findViewById(R.id.menu_button); + button.setText("Menu"); + mPopupList = new PopupList(context, button); + button.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + mPopupList.show(); + } + }); + } + + public void setOptionsMenu(SimpleMenu menu) { + mPopupList.clearItems(); + for (int i = 0, n = menu.getItemCount(); i < n; ++i) { + SimpleMenu.Item item = menu.getItem(i); + mPopupList.addItem(item.id, item.title); + } + } +} diff --git a/src/com/android/gallery3d/actionbar/SimpleActionMode.java b/src/com/android/gallery3d/actionbar/SimpleActionMode.java new file mode 100644 index 000000000..33733d173 --- /dev/null +++ b/src/com/android/gallery3d/actionbar/SimpleActionMode.java @@ -0,0 +1,44 @@ +package com.android.gallery3d.actionbar; + +import android.content.Intent; +import android.view.View; + +public class SimpleActionMode implements ActionModeInterface { + + @Override + public void setMenuItemVisible(int menuItemId, boolean visible) { + } + + @Override + public void setMenuItemTitle(int menuItemId, String title) { + } + + @Override + public void setMenuItemIntent(int menuItemId, Intent intent) { + } + + @Override + public void inflateMenu(int operation) { + } + + @Override + public void setCustomView(View view) { + } + + @Override + public void finish() { + } + + @Override + public void setShareIntent(Intent intent) { + } + + @Override + public boolean hasShareButton() { + return false; + } + + @Override + public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) { + } +} diff --git a/src/com/android/gallery3d/actionbar/SimpleMenu.java b/src/com/android/gallery3d/actionbar/SimpleMenu.java new file mode 100644 index 000000000..8bc55808a --- /dev/null +++ b/src/com/android/gallery3d/actionbar/SimpleMenu.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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.android.gallery3d.actionbar; + +import android.content.Intent; + +import java.util.ArrayList; + +public class SimpleMenu implements MenuHolder { + // These values are copied from MenuItem in HoneyComb + private static final int SHOW_AS_ACTION_NEVER = 0; + private static final int SHOW_AS_ACTION_ALWAYS = 1; + private static final int SHOW_AS_ACTION_IFROOM = 2; + private static final int SHOW_AS_ACTION_WITH_TEXT = 4; + + // A bit mask to get WHEN to show as action. It is one of the following + // values: SHOW_AS_ACTION_NEVER, SHOW_AS_ACTION_ALWAYS, or + // SHOW_AS_ACTION_IFROOM. + private static final int SHOW_AS_ACTION_MASK = 0x03; + + public static class Item { + public int id; + public int iconId; + public String title; + public boolean visible; + public int showAsAction; + public Intent intent; + } + + private ArrayList mItems = new ArrayList(); + + public void clear() { + mItems.clear(); + } + + public void addItem(Item item) { + mItems.add(item); + } + + @Override + public void setMenuItemVisible(int menuItemId, boolean visible) { + Item item = findItem(menuItemId); + if (item != null) item.visible = visible; + } + + public int getItemCount() { + return mItems.size(); + } + + public Item getItem(int index) { + return mItems.get(index); + } + + public Item findItem(int menuItemId) { + for (int i = 0, n = mItems.size(); i < n; ++i) { + Item item = mItems.get(i); + if (item.id == menuItemId) return item; + } + return null; + } + + @Override + public void setMenuItemTitle(int menuItemId, String title) { + Item item = findItem(menuItemId); + if (item != null) item.title = title; + } + + @Override + public void setMenuItemIntent(int menuItemId, Intent intent) { + Item item = findItem(menuItemId); + if (item != null) item.intent = intent; + } +} diff --git a/src/com/android/gallery3d/actionbar/SimpleMenuInflater.java b/src/com/android/gallery3d/actionbar/SimpleMenuInflater.java new file mode 100644 index 000000000..885a4d3bc --- /dev/null +++ b/src/com/android/gallery3d/actionbar/SimpleMenuInflater.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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.android.gallery3d.actionbar; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.util.AttributeSet; +import android.util.Xml; +import android.view.InflateException; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +public class SimpleMenuInflater { + + private static final String TAG_MENU = "menu"; + private static final String TAG_ITEM = "item"; + + private final Context mContext; + + public SimpleMenuInflater(Context context) { + mContext = context; + } + + public SimpleMenu inflate(SimpleMenu menu, int menuRes) throws InflateException { + XmlResourceParser parser = mContext.getResources().getXml(menuRes); + try { + return inflateInternal(menu, parser); + } catch (XmlPullParserException e) { + throw new InflateException(e); + } catch (IOException e) { + throw new InflateException(e); + } finally { + if (parser != null) parser.close(); + } + } + + private SimpleMenu inflateInternal(SimpleMenu menu, XmlPullParser parser) + throws XmlPullParserException, IOException { + int eventType = parser.getEventType(); + do { + if (eventType == XmlPullParser.START_TAG) { + String tagName = parser.getName(); + if (TAG_MENU.equals(tagName)) { + eventType = parser.next(); + break; + } + throw new RuntimeException("unexpected tag: " + tagName); + } + eventType = parser.next(); + } while (eventType != XmlPullParser.END_DOCUMENT); + + if (menu == null) menu = new SimpleMenu(); + AttributeSet attrs = Xml.asAttributeSet(parser); + + boolean reachedEndOfMenu = false; + while (!reachedEndOfMenu) { + switch (eventType) { + case XmlPullParser.START_TAG: { + String tagName = parser.getName(); + if (TAG_ITEM.equals(tagName)) { + menu.addItem(parseItem(attrs)); + } else if (TAG_MENU.equals(tagName)) { + throw new RuntimeException("nested menu not supported"); + } else { + // ignore all other tags + parser.next(); + } + break; + } + case XmlPullParser.END_TAG: { + String tagName = parser.getName(); + if (TAG_MENU.equals(tagName)) { + reachedEndOfMenu = true; + break; + } + break; + } + case XmlPullParser.END_DOCUMENT: { + throw new RuntimeException("unexpected end of document"); + } + } + eventType = parser.next(); + } + return menu; + } + + private static final String ATTR_ID = "id"; + private static final String ATTR_ICON = "icon"; + private static final String ATTR_TITLE = "title"; + private static final String ATTR_VISIBLE = "visible"; + private static final String ATTR_SHOW_AS_ACTION = "showAsAction"; + + private SimpleMenu.Item parseItem(AttributeSet attrs) { + SimpleMenu.Item item = new SimpleMenu.Item(); + Resources res = mContext.getResources(); + for (int i = 0, n = attrs.getAttributeCount(); i < n; ++i) { + String attrName = attrs.getAttributeName(i); + if (ATTR_ID.equals(attrName)) { + item.id = attrs.getAttributeResourceValue(i, 0); + } else if (ATTR_ICON.equals(attrName)) { + item.iconId = attrs.getAttributeResourceValue(i, 0); + } else if (ATTR_TITLE.equals(attrName)) { + int id = attrs.getAttributeResourceValue(i, 0); + item.title = id == 0 ? null : res.getString(id); + } else if (ATTR_VISIBLE.equals(attrName)) { + item.visible = attrs.getAttributeBooleanValue(i, true); + } else if (ATTR_SHOW_AS_ACTION.equals(attrName)) { + item.showAsAction = attrs.getAttributeIntValue(i, 0); + } + } + return item; + } + +} diff --git a/src/com/android/gallery3d/actionbar/SystemActionModeWrapper.java b/src/com/android/gallery3d/actionbar/SystemActionModeWrapper.java index 97261e657..af925eacc 100644 --- a/src/com/android/gallery3d/actionbar/SystemActionModeWrapper.java +++ b/src/com/android/gallery3d/actionbar/SystemActionModeWrapper.java @@ -34,10 +34,11 @@ public class SystemActionModeWrapper implements ActionModeInterface { private ActionMode mActionMode; private Menu mMenu; private MenuItem mShareMenuItem; - private ShareActionProvider mShareActionProvider; + private final ShareActionProvider mShareActionProvider; public SystemActionModeWrapper(Activity activity, ActionModeInterface.Callback callback) { // mActionMode will be set in callback.onCreateActionMode + mShareActionProvider = new ShareActionProvider(activity); activity.startActionMode(new CallbackWrapper(callback)); } @@ -86,10 +87,9 @@ public class SystemActionModeWrapper implements ActionModeInterface { public void inflateMenu(int menuRes) { Utils.assertTrue(mMenu != null); mActionMode.getMenuInflater().inflate(menuRes, mMenu); - mShareActionProvider = null; mShareMenuItem = mMenu.findItem(R.id.action_share); if (mShareMenuItem != null) { - mShareActionProvider = (ShareActionProvider) mShareMenuItem.getActionProvider(); + mShareMenuItem.setActionProvider(mShareActionProvider); } } diff --git a/src/com/android/gallery3d/app/ActivityState.java b/src/com/android/gallery3d/app/ActivityState.java index ca0816c8d..6335d0575 100644 --- a/src/com/android/gallery3d/app/ActivityState.java +++ b/src/com/android/gallery3d/app/ActivityState.java @@ -33,6 +33,8 @@ import android.view.MenuItem; import android.view.Window; import android.view.WindowManager; +import com.android.gallery3d.actionbar.ActionBarInterface; +import com.android.gallery3d.actionbar.ActionBarUtils; import com.android.gallery3d.ui.GLView; abstract public class ActivityState { @@ -142,7 +144,7 @@ abstract public class ActivityState { // should only be called by StateManager void resume() { AbstractGalleryActivity activity = (AbstractGalleryActivity) mActivity; - ActionBar actionBar = activity.getActionBar(); + ActionBarInterface actionBar = ActionBarUtils.getActionBar(activity); if (actionBar != null) { if ((mFlags & FLAG_HIDE_ACTION_BAR) != 0) { actionBar.hide(); diff --git a/src/com/android/gallery3d/ui/PopupList.java b/src/com/android/gallery3d/ui/PopupList.java index a5fbb09a8..9cd381430 100644 --- a/src/com/android/gallery3d/ui/PopupList.java +++ b/src/com/android/gallery3d/ui/PopupList.java @@ -1,4 +1,18 @@ -// Copyright 2012 Google Inc. All Rights Reserved. +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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.android.gallery3d.ui; @@ -65,6 +79,10 @@ public class PopupList { mItems.add(new Item(id, title)); } + public void clearItems() { + mItems.clear(); + } + private final PopupWindow.OnDismissListener mOnDismissListener = new PopupWindow.OnDismissListener() { @SuppressWarnings("deprecation") @@ -134,7 +152,7 @@ public class PopupList { } private PopupWindow createPopupWindow() { - PopupWindow popup = new PopupWindow(); + PopupWindow popup = new PopupWindow(mContext); popup.setOnDismissListener(mOnDismissListener); popup.setBackgroundDrawable(mContext.getResources().getDrawable( -- cgit v1.2.3