Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11ed1d6c authored by Adam Powell's avatar Adam Powell
Browse files

Fix bugs around restoring submenu state after activity teardown/restore

Change-Id: I6cb5b3cad39b141dff84b8e0ca62f8f0a76a03b1
parent eb982f39
Loading
Loading
Loading
Loading
+78 −2
Original line number Diff line number Diff line
@@ -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) {
        }
    }

+10 −0
Original line number Diff line number Diff line
@@ -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;
    }
}
+53 −1
Original line number Diff line number Diff line
@@ -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;
        }

    }
}
+27 −0
Original line number Diff line number Diff line
@@ -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();
+55 −2
Original line number Diff line number Diff line
@@ -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;
    }
Loading