diff options
Diffstat (limited to 'core/java/com/android/internal/view/menu')
7 files changed, 259 insertions, 5 deletions
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index b86eb13..9c06d69 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -20,7 +20,8 @@ import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView; import android.content.Context; import android.content.res.Resources; -import android.util.Log; +import android.os.Parcel; +import android.os.Parcelable; import android.util.SparseBooleanArray; import android.view.MenuItem; import android.view.SoundEffectConstants; @@ -60,6 +61,9 @@ public class ActionMenuPresenter extends BaseMenuPresenter { private OpenOverflowRunnable mPostedOpenRunnable; + final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback(); + int mOpenSubMenuId; + public ActionMenuPresenter() { super(com.android.internal.R.layout.action_menu_layout, com.android.internal.R.layout.action_menu_item_layout); @@ -196,8 +200,12 @@ public class ActionMenuPresenter extends BaseMenuPresenter { topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu(); } View anchor = findViewForItem(topSubMenu.getItem()); - if (anchor == null) return false; + if (anchor == null) { + if (mOverflowButton == null) return false; + anchor = mOverflowButton; + } + mOpenSubMenuId = subMenu.getItem().getItemId(); mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu); mActionButtonPopup.setAnchorView(anchor); mActionButtonPopup.show(); @@ -426,6 +434,57 @@ public class ActionMenuPresenter extends BaseMenuPresenter { super.onCloseMenu(menu, allMenusAreClosing); } + @Override + public Parcelable onSaveInstanceState() { + SavedState state = new SavedState(); + state.openSubMenuId = mOpenSubMenuId; + return state; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + SavedState saved = (SavedState) state; + if (saved.openSubMenuId > 0) { + MenuItem item = mMenu.findItem(saved.openSubMenuId); + if (item != null) { + SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); + onSubMenuSelected(subMenu); + } + } + } + + private static class SavedState implements Parcelable { + public int openSubMenuId; + + SavedState() { + } + + SavedState(Parcel in) { + openSubMenuId = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(openSubMenuId); + } + + public static final Parcelable.Creator<SavedState> CREATOR + = new Parcelable.Creator<SavedState>() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + private class OverflowMenuButton extends ImageButton implements ActionMenuChildView { public OverflowMenuButton(Context context) { super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle); @@ -460,6 +519,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter { public OverflowPopup(Context context, MenuBuilder menu, View anchorView, boolean overflowOnly) { super(context, menu, anchorView, overflowOnly); + setCallback(mPopupPresenterCallback); } @Override @@ -482,6 +542,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter { // Give a reasonable anchor to nested submenus. setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton); } + + setCallback(mPopupPresenterCallback); } @Override @@ -489,6 +551,20 @@ public class ActionMenuPresenter extends BaseMenuPresenter { super.onDismiss(); mSubMenu.close(); mActionButtonPopup = null; + mOpenSubMenuId = 0; + } + } + + private class PopupPresenterCallback implements MenuPresenter.Callback { + + @Override + public boolean onOpenSubMenu(MenuBuilder subMenu) { + mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId(); + return false; + } + + @Override + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { } } diff --git a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java index ddbb08c..ed9d34a 100644 --- a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java @@ -39,6 +39,8 @@ public abstract class BaseMenuPresenter implements MenuPresenter { protected MenuView mMenuView; + private int mId; + /** * Construct a new BaseMenuPresenter. * @@ -200,4 +202,12 @@ public abstract class BaseMenuPresenter implements MenuPresenter { public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { return false; } + + public int getId() { + return mId; + } + + public void setId(int id) { + mId = id; + } } diff --git a/core/java/com/android/internal/view/menu/IconMenuPresenter.java b/core/java/com/android/internal/view/menu/IconMenuPresenter.java index f717904..56128d4 100644 --- a/core/java/com/android/internal/view/menu/IconMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/IconMenuPresenter.java @@ -23,6 +23,7 @@ import android.os.Parcelable; import android.util.SparseArray; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -35,7 +36,12 @@ public class IconMenuPresenter extends BaseMenuPresenter { private IconMenuItemView mMoreView; private int mMaxItems = -1; + int mOpenSubMenuId; + SubMenuPresenterCallback mSubMenuPresenterCallback = new SubMenuPresenterCallback(); + MenuDialogHelper mOpenSubMenu; + private static final String VIEWS_TAG = "android:menu:icon"; + private static final String OPEN_SUBMENU_KEY = "android:menu:icon:submenu"; public IconMenuPresenter() { super(com.android.internal.R.layout.icon_menu_layout, @@ -86,7 +92,11 @@ public class IconMenuPresenter extends BaseMenuPresenter { if (!subMenu.hasVisibleItems()) return false; // The window manager will give us a token. - new MenuDialogHelper(subMenu).show(null); + MenuDialogHelper helper = new MenuDialogHelper(subMenu); + helper.setPresenterCallback(mSubMenuPresenterCallback); + helper.show(null); + mOpenSubMenu = helper; + mOpenSubMenuId = subMenu.getItem().getItemId(); super.onSubMenuSelected(subMenu); return true; } @@ -137,5 +147,47 @@ public class IconMenuPresenter extends BaseMenuPresenter { if (viewStates != null) { ((View) mMenuView).restoreHierarchyState(viewStates); } + int subMenuId = inState.getInt(OPEN_SUBMENU_KEY, 0); + if (subMenuId > 0 && mMenu != null) { + MenuItem item = mMenu.findItem(subMenuId); + if (item != null) { + onSubMenuSelected((SubMenuBuilder) item.getSubMenu()); + } + } + } + + @Override + public Parcelable onSaveInstanceState() { + if (mMenuView == null) { + return null; + } + + Bundle state = new Bundle(); + saveHierarchyState(state); + if (mOpenSubMenuId > 0) { + state.putInt(OPEN_SUBMENU_KEY, mOpenSubMenuId); + } + return state; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + restoreHierarchyState((Bundle) state); + } + + class SubMenuPresenterCallback implements MenuPresenter.Callback { + @Override + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + mOpenSubMenuId = 0; + mOpenSubMenu.dismiss(); + mOpenSubMenu = null; + } + + @Override + public boolean onOpenSubMenu(MenuBuilder subMenu) { + mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId(); + return false; + } + } } diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java index 27e4191..146c7ac 100644 --- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java @@ -47,6 +47,8 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick private Callback mCallback; private MenuAdapter mAdapter; + private int mId; + public static final String VIEWS_TAG = "android:menu:list"; /** @@ -182,6 +184,31 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick } } + public void setId(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + + @Override + public Parcelable onSaveInstanceState() { + if (mMenuView == null) { + return null; + } + + Bundle state = new Bundle(); + saveHierarchyState(state); + return state; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + restoreHierarchyState((Bundle) state); + } + private class MenuAdapter extends BaseAdapter { public int getCount() { ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index fdfa954..a4edbc5 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -25,8 +25,8 @@ import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.os.Parcelable; -import android.util.Log; import android.util.SparseArray; import android.view.ContextMenu.ContextMenuInfo; import android.view.KeyCharacterMap; @@ -38,7 +38,6 @@ import android.view.View; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -49,6 +48,8 @@ import java.util.concurrent.CopyOnWriteArrayList; public class MenuBuilder implements Menu { private static final String LOGTAG = "MenuBuilder"; + private static final String PRESENTER_KEY = "android:menu:presenters"; + private static final int[] sCategoryToOrder = new int[] { 1, /* No category */ 4, /* CONTAINER */ @@ -254,6 +255,58 @@ public class MenuBuilder implements Menu { return result; } + private void dispatchSaveInstanceState(Bundle outState) { + if (mPresenters.isEmpty()) return; + + SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>(); + + for (WeakReference<MenuPresenter> ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else { + final int id = presenter.getId(); + if (id > 0) { + final Parcelable state = presenter.onSaveInstanceState(); + if (state != null) { + presenterStates.put(id, state); + } + } + } + } + + outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates); + } + + private void dispatchRestoreInstanceState(Bundle state) { + SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY); + + if (presenterStates == null || mPresenters.isEmpty()) return; + + for (WeakReference<MenuPresenter> ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else { + final int id = presenter.getId(); + if (id > 0) { + Parcelable parcel = presenterStates.get(id); + if (parcel != null) { + presenter.onRestoreInstanceState(parcel); + } + } + } + } + } + + public void savePresenterStates(Bundle outState) { + dispatchSaveInstanceState(outState); + } + + public void restorePresenterStates(Bundle state) { + dispatchRestoreInstanceState(state); + } + public void setCallback(Callback cb) { mCallback = cb; } diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index cffbb4e..4ecc828 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -18,6 +18,7 @@ package com.android.internal.view.menu; import android.content.Context; import android.content.res.Resources; +import android.os.Parcelable; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -296,4 +297,18 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On return convertView; } } + + @Override + public int getId() { + return 0; + } + + @Override + public Parcelable onSaveInstanceState() { + return null; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + } } diff --git a/core/java/com/android/internal/view/menu/MenuPresenter.java b/core/java/com/android/internal/view/menu/MenuPresenter.java index bd66448..d913a39 100644 --- a/core/java/com/android/internal/view/menu/MenuPresenter.java +++ b/core/java/com/android/internal/view/menu/MenuPresenter.java @@ -17,6 +17,7 @@ package com.android.internal.view.menu; import android.content.Context; +import android.os.Parcelable; import android.view.Menu; import android.view.ViewGroup; @@ -125,4 +126,24 @@ public interface MenuPresenter { * @return true if this presenter collapsed the action view, false otherwise. */ public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item); + + /** + * Returns an ID for determining how to save/restore instance state. + * @return a valid ID value. + */ + public int getId(); + + /** + * Returns a Parcelable describing the current state of the presenter. + * It will be passed to the {@link #onRestoreInstanceState(Parcelable)} + * method of the presenter sharing the same ID later. + * @return The saved instance state + */ + public Parcelable onSaveInstanceState(); + + /** + * Supplies the previously saved instance state to be restored. + * @param state The previously saved instance state + */ + public void onRestoreInstanceState(Parcelable state); } |