ActionMenuPresenter.java revision ac00a989afc2f1c559fc33174f481a0a0ef5b3d8
1bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/*
249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2014 The Android Open Source Project
3bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell *
4bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Licensed under the Apache License, Version 2.0 (the "License");
5bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * you may not use this file except in compliance with the License.
6bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * You may obtain a copy of the License at
7bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell *
8bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell *      http://www.apache.org/licenses/LICENSE-2.0
9bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell *
10bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Unless required by applicable law or agreed to in writing, software
11bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * distributed under the License is distributed on an "AS IS" BASIS,
12bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * See the License for the specific language governing permissions and
14bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * limitations under the License.
15bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
16bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
1749c78900da0d43140fb602431fb93212bd7f6c70Chris Banespackage android.support.v7.widget;
18bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
19bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Context;
20bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.Configuration;
21bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.Resources;
22ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banesimport android.graphics.Rect;
23ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banesimport android.graphics.drawable.Drawable;
24bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.os.Parcel;
25bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.os.Parcelable;
26ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banesimport android.support.v4.graphics.drawable.DrawableCompat;
2749c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.ActionProvider;
2849c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.GravityCompat;
29da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
3049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.transition.ActionBarTransition;
31da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.internal.view.ActionBarPolicy;
3249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.ActionMenuItemView;
3349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.BaseMenuPresenter;
3449c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.MenuBuilder;
3549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.MenuItemImpl;
3649c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.MenuPopupHelper;
3749c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.MenuView;
3849c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.SubMenuBuilder;
39bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.util.SparseBooleanArray;
4030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
41bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.SoundEffectConstants;
42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View;
43bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View.MeasureSpec;
44bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewGroup;
45bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.ImageButton;
46bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
47bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList;
48bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
49bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/**
50bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * MenuPresenter for building action menus as seen in the action bar and action modes.
5189208232f3b5d1451408d787872504a190bc7ee0Chris Banes *
5289208232f3b5d1451408d787872504a190bc7ee0Chris Banes * @hide
53bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
54bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellpublic class ActionMenuPresenter extends BaseMenuPresenter
5520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        implements ActionProvider.SubUiVisibilityListener {
56bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
5720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private static final String TAG = "ActionMenuPresenter";
58bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
5920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private View mOverflowButton;
6020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private boolean mReserveOverflow;
6120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private boolean mReserveOverflowSet;
6220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private int mWidthLimit;
6320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private int mActionItemWidthLimit;
6420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private int mMaxItems;
6520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private boolean mMaxItemsSet;
6620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private boolean mStrictWidthLimit;
6720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private boolean mWidthLimitSet;
6820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private boolean mExpandedActionViewsExclusive;
69bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
7020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private int mMinCellSize;
71bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
7220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    // Group IDs that have been added as actions - used temporarily, allocated here for reuse.
7320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray();
74bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
7520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private View mScrapActionButtonView;
76bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
7720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private OverflowPopup mOverflowPopup;
7820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private ActionButtonSubmenu mActionButtonPopup;
79bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
8020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private OpenOverflowRunnable mPostedOpenRunnable;
8149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private ActionMenuPopupCallback mPopupCallback;
82bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
8320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
8420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    int mOpenSubMenuId;
85bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
8620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public ActionMenuPresenter(Context context) {
87ee7c9fb199e9b9af8d40a1f9e27d85465acf8301Chris Banes        super(context, R.layout.abc_action_menu_layout, R.layout.abc_action_menu_item_layout);
88bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
89bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
9020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    @Override
9120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void initForMenu(Context context, MenuBuilder menu) {
9220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        super.initForMenu(context, menu);
93bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
9420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final Resources res = context.getResources();
95bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
9620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final ActionBarPolicy abp = ActionBarPolicy.get(context);
9720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (!mReserveOverflowSet) {
9820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mReserveOverflow = abp.showsOverflowMenuButton();
9920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
100bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
10120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (!mWidthLimitSet) {
10220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mWidthLimit = abp.getEmbeddedMenuWidthLimit();
10320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
104bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
10520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        // Measure for initial configuration
10620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (!mMaxItemsSet) {
10720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mMaxItems = abp.getMaxActionButtons();
10820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
109bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
11020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        int width = mWidthLimit;
11120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mReserveOverflow) {
11220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (mOverflowButton == null) {
11320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mOverflowButton = new OverflowMenuButton(mSystemContext);
11420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
11520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mOverflowButton.measure(spec, spec);
11620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
11720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            width -= mOverflowButton.getMeasuredWidth();
11820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        } else {
11920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mOverflowButton = null;
12020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
121bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
12220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mActionItemWidthLimit = width;
123bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
12420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mMinCellSize = (int) (ActionMenuView.MIN_CELL_SIZE * res.getDisplayMetrics().density);
125bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
12620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        // Drop a scrap view as it may no longer reflect the proper context/config.
12720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mScrapActionButtonView = null;
128bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
12920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
13020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void onConfigurationChanged(Configuration newConfig) {
13120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (!mMaxItemsSet) {
13220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mMaxItems = mContext.getResources().getInteger(
13307a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes                    R.integer.abc_max_action_buttons);
134bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
13520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mMenu != null) {
136d900fe072335d488f883585e3f686ef955d1ccc9Chris Banes            mMenu.onItemsChanged(true);
137bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
13820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
139bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
14020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void setWidthLimit(int width, boolean strict) {
14120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mWidthLimit = width;
14220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mStrictWidthLimit = strict;
14320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mWidthLimitSet = true;
144bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
145bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
14620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void setReserveOverflow(boolean reserveOverflow) {
14720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mReserveOverflow = reserveOverflow;
14820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mReserveOverflowSet = true;
14920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
150bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
15120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void setItemLimit(int itemCount) {
15220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mMaxItems = itemCount;
15320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mMaxItemsSet = true;
15420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
155bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
15620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void setExpandedActionViewsExclusive(boolean isExclusive) {
15720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mExpandedActionViewsExclusive = isExclusive;
158bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
159bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
16020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    @Override
16120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public MenuView getMenuView(ViewGroup root) {
16220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        MenuView result = super.getMenuView(root);
16320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        ((ActionMenuView) result).setPresenter(this);
16420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return result;
165bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
166bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
16720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    @Override
16849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public View getItemView(final MenuItemImpl item, View convertView, ViewGroup parent) {
16920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        View actionView = item.getActionView();
17020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (actionView == null || item.hasCollapsibleActionView()) {
17120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            actionView = super.getItemView(item, convertView, parent);
17220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
17320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
174bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
17520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final ActionMenuView menuParent = (ActionMenuView) parent;
17620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
17720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (!menuParent.checkLayoutParams(lp)) {
17820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
17920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
18020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return actionView;
181bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
182bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
18320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    @Override
18420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) {
18520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        itemView.initialize(item, 0);
18620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
18720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final ActionMenuView menuView = (ActionMenuView) mMenuView;
18849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
18981173a86853974bb27d4197a0f0768922f8205caTrevor Johns        actionItemView.setItemInvoker(menuView);
19049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
19149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPopupCallback == null) {
19249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            mPopupCallback = new ActionMenuPopupCallback();
19349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
19449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        actionItemView.setPopupCallback(mPopupCallback);
195bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
196bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
197bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    @Override
19820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) {
19920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return item.isActionButton();
200bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
201bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
202bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    @Override
20320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void updateMenuView(boolean cleared) {
20449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final ViewGroup menuViewParent = (ViewGroup) ((View) mMenuView).getParent();
20549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (menuViewParent != null) {
20649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            ActionBarTransition.beginDelayedTransition(menuViewParent);
20749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
20820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        super.updateMenuView(cleared);
20920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
21049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        ((View) mMenuView).requestLayout();
211176a17e30644b1d5a4206cc462268d151e43949bChris Banes
21220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mMenu != null) {
21320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final ArrayList<MenuItemImpl> actionItems = mMenu.getActionItems();
21420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final int count = actionItems.size();
21520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            for (int i = 0; i < count; i++) {
21630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                final ActionProvider provider = actionItems.get(i).getSupportActionProvider();
21720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (provider != null) {
21820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    provider.setSubUiVisibilityListener(this);
21920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
22020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
22120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
222bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
22320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final ArrayList<MenuItemImpl> nonActionItems = mMenu != null ?
22420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mMenu.getNonActionItems() : null;
225bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
22620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        boolean hasOverflow = false;
22720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mReserveOverflow && nonActionItems != null) {
22820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final int count = nonActionItems.size();
22920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (count == 1) {
23020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                hasOverflow = !nonActionItems.get(0).isActionViewExpanded();
23120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            } else {
23220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                hasOverflow = count > 0;
23320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
23420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
235bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
23620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (hasOverflow) {
23720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (mOverflowButton == null) {
23820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mOverflowButton = new OverflowMenuButton(mSystemContext);
23920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
24020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            ViewGroup parent = (ViewGroup) mOverflowButton.getParent();
24120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (parent != mMenuView) {
24220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (parent != null) {
24320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    parent.removeView(mOverflowButton);
24420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
24520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                ActionMenuView menuView = (ActionMenuView) mMenuView;
24620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                menuView.addView(mOverflowButton, menuView.generateOverflowButtonLayoutParams());
24720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
24820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        } else if (mOverflowButton != null && mOverflowButton.getParent() == mMenuView) {
24920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            ((ViewGroup) mMenuView).removeView(mOverflowButton);
25020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
251bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
25220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        ((ActionMenuView) mMenuView).setOverflowReserved(mReserveOverflow);
253bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
254bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
255bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    @Override
25620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean filterLeftoverView(ViewGroup parent, int childIndex) {
25749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (parent.getChildAt(childIndex) == mOverflowButton) return false;
25820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return super.filterLeftoverView(parent, childIndex);
25920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
26020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
26120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
26249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (!subMenu.hasVisibleItems()) return false;
26320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
26420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        SubMenuBuilder topSubMenu = subMenu;
26520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        while (topSubMenu.getParentMenu() != mMenu) {
26620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu();
26720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
26820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        View anchor = findViewForItem(topSubMenu.getItem());
26920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (anchor == null) {
27049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (mOverflowButton == null) return false;
27120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            anchor = mOverflowButton;
27220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
27320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
27420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mOpenSubMenuId = subMenu.getItem().getItemId();
27549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu);
27649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mActionButtonPopup.setAnchorView(anchor);
27749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mActionButtonPopup.show();
27820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        super.onSubMenuSelected(subMenu);
279bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        return true;
28020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
28120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
28220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private View findViewForItem(MenuItem item) {
28320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final ViewGroup parent = (ViewGroup) mMenuView;
28449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (parent == null) return null;
28520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
28620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final int count = parent.getChildCount();
28720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        for (int i = 0; i < count; i++) {
28820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final View child = parent.getChildAt(i);
28920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (child instanceof MenuView.ItemView &&
29020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    ((MenuView.ItemView) child).getItemData() == item) {
29120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                return child;
29220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
29320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
29420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return null;
29520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
29620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
29720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
29820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Display the overflow menu if one is present.
29920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return true if the overflow menu was shown, false otherwise.
30020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
30120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean showOverflowMenu() {
30220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mReserveOverflow && !isOverflowMenuShowing() && mMenu != null && mMenuView != null &&
30349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                mPostedOpenRunnable == null && !mMenu.getNonActionItems().isEmpty()) {
30420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            OverflowPopup popup = new OverflowPopup(mContext, mMenu, mOverflowButton, true);
30520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mPostedOpenRunnable = new OpenOverflowRunnable(popup);
30620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            // Post this for later; we might still need a layout for the anchor to be right.
30720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            ((View) mMenuView).post(mPostedOpenRunnable);
30820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
30920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            // ActionMenuPresenter uses null as a callback argument here
31020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            // to indicate overflow is opening.
31120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            super.onSubMenuSelected(null);
31220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
31320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return true;
31420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
31520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return false;
31620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
31720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
31820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
31920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Hide the overflow menu if it is currently showing.
32020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
32120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return true if the overflow menu was hidden, false otherwise.
32220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
32320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean hideOverflowMenu() {
32420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPostedOpenRunnable != null && mMenuView != null) {
32520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            ((View) mMenuView).removeCallbacks(mPostedOpenRunnable);
32620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mPostedOpenRunnable = null;
32720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return true;
32820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
32920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
33020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        MenuPopupHelper popup = mOverflowPopup;
33120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (popup != null) {
33220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            popup.dismiss();
33320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return true;
33420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
33520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return false;
33620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
33720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
33820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
33920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Dismiss all popup menus - overflow and submenus.
34020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return true if popups were dismissed, false otherwise. (This can be because none were open.)
34120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
34220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean dismissPopupMenus() {
34320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        boolean result = hideOverflowMenu();
34420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        result |= hideSubMenus();
34520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return result;
34620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
34720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
34820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
34920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Dismiss all submenu popups.
35020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
35120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return true if popups were dismissed, false otherwise. (This can be because none were open.)
35220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
35320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean hideSubMenus() {
35420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mActionButtonPopup != null) {
35520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mActionButtonPopup.dismiss();
35620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return true;
35720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
35820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return false;
35920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
36020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
36120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
36220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return true if the overflow menu is currently showing
36320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
36420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean isOverflowMenuShowing() {
36520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return mOverflowPopup != null && mOverflowPopup.isShowing();
36620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
36720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
36849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public boolean isOverflowMenuShowPending() {
36949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return mPostedOpenRunnable != null || isOverflowMenuShowing();
37049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
37149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
37220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
37320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return true if space has been reserved in the action menu for an overflow item.
37420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
37520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean isOverflowReserved() {
37620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return mReserveOverflow;
37720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    }
37820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
37920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public boolean flagActionItems() {
38020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems();
38120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final int itemsSize = visibleItems.size();
38220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        int maxActions = mMaxItems;
38320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        int widthLimit = mActionItemWidthLimit;
38420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
38520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final ViewGroup parent = (ViewGroup) mMenuView;
38620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
38720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        int requiredItems = 0;
38820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        int requestedItems = 0;
38920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        int firstActionWidth = 0;
39020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        boolean hasOverflow = false;
39120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        for (int i = 0; i < itemsSize; i++) {
39220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            MenuItemImpl item = visibleItems.get(i);
39320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (item.requiresActionButton()) {
39420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                requiredItems++;
39520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            } else if (item.requestsActionButton()) {
39620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                requestedItems++;
39720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            } else {
39820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                hasOverflow = true;
39920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
40020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (mExpandedActionViewsExclusive && item.isActionViewExpanded()) {
40120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                // Overflow everything if we have an expanded action view and we're
40220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                // space constrained.
40320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                maxActions = 0;
40420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
40520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
40620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
40720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        // Reserve a spot for the overflow item if needed.
40820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mReserveOverflow &&
40920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                (hasOverflow || requiredItems + requestedItems > maxActions)) {
41020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            maxActions--;
41120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
41220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        maxActions -= requiredItems;
413bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
41420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        final SparseBooleanArray seenGroups = mActionButtonGroups;
41520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        seenGroups.clear();
41620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
41720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        int cellSize = 0;
41820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        int cellsRemaining = 0;
41920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mStrictWidthLimit) {
42020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            cellsRemaining = widthLimit / mMinCellSize;
42120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final int cellSizeRemaining = widthLimit % mMinCellSize;
42220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            cellSize = mMinCellSize + cellSizeRemaining / cellsRemaining;
42320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
42420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
42520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        // Flag as many more requested items as will fit.
42620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        for (int i = 0; i < itemsSize; i++) {
42720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            MenuItemImpl item = visibleItems.get(i);
42820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
42920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (item.requiresActionButton()) {
43020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                View v = getItemView(item, mScrapActionButtonView, parent);
43120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (mScrapActionButtonView == null) {
43220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    mScrapActionButtonView = v;
43320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
43420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (mStrictWidthLimit) {
43520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    cellsRemaining -= ActionMenuView.measureChildForCells(v,
43620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                            cellSize, cellsRemaining, querySpec, 0);
43720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                } else {
43820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    v.measure(querySpec, querySpec);
43920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
44020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                final int measuredWidth = v.getMeasuredWidth();
44120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                widthLimit -= measuredWidth;
44220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (firstActionWidth == 0) {
44320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    firstActionWidth = measuredWidth;
44420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
44520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                final int groupId = item.getGroupId();
44620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (groupId != 0) {
44720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    seenGroups.put(groupId, true);
44820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
44920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                item.setIsActionButton(true);
45020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            } else if (item.requestsActionButton()) {
45120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                // Items in a group with other items that already have an action slot
45220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                // can break the max actions rule, but not the width limit.
45320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                final int groupId = item.getGroupId();
45420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                final boolean inGroup = seenGroups.get(groupId);
45520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0 &&
45620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        (!mStrictWidthLimit || cellsRemaining > 0);
45720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
45820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (isAction) {
45920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    View v = getItemView(item, mScrapActionButtonView, parent);
46020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    if (mScrapActionButtonView == null) {
46120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        mScrapActionButtonView = v;
46220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    }
46320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    if (mStrictWidthLimit) {
46420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        final int cells = ActionMenuView.measureChildForCells(v,
46520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                                cellSize, cellsRemaining, querySpec, 0);
46620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        cellsRemaining -= cells;
46720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        if (cells == 0) {
46820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                            isAction = false;
46920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        }
47020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    } else {
47120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        v.measure(querySpec, querySpec);
47220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    }
47320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    final int measuredWidth = v.getMeasuredWidth();
47420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    widthLimit -= measuredWidth;
47520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    if (firstActionWidth == 0) {
47620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        firstActionWidth = measuredWidth;
47720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    }
47820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
47920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    if (mStrictWidthLimit) {
48020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        isAction &= widthLimit >= 0;
48120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    } else {
48220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        // Did this push the entire first item past the limit?
48320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        isAction &= widthLimit + firstActionWidth > 0;
48420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    }
48520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
48620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
48720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (isAction && groupId != 0) {
48820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    seenGroups.put(groupId, true);
48920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                } else if (inGroup) {
49020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    // We broke the width limit. Demote the whole group, they all overflow now.
49120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    seenGroups.put(groupId, false);
49220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    for (int j = 0; j < i; j++) {
49320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        MenuItemImpl areYouMyGroupie = visibleItems.get(j);
49420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        if (areYouMyGroupie.getGroupId() == groupId) {
49520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                            // Give back the action slot
49649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                            if (areYouMyGroupie.isActionButton()) maxActions++;
49720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                            areYouMyGroupie.setIsActionButton(false);
49820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        }
49920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    }
50020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
50120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
50249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (isAction) maxActions--;
50320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
50420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                item.setIsActionButton(isAction);
50549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            } else {
50649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                // Neither requires nor requests an action button.
50749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                item.setIsActionButton(false);
50820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
50920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
51020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return true;
511bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
512bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
51320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    @Override
51420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
51520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        dismissPopupMenus();
51620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        super.onCloseMenu(menu, allMenusAreClosing);
517bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
518bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
51920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    @Override
52020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public Parcelable onSaveInstanceState() {
52120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        SavedState state = new SavedState();
52220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        state.openSubMenuId = mOpenSubMenuId;
52320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        return state;
524bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
525bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
52620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    @Override
52720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void onRestoreInstanceState(Parcelable state) {
52820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        SavedState saved = (SavedState) state;
52920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (saved.openSubMenuId > 0) {
53020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            MenuItem item = mMenu.findItem(saved.openSubMenuId);
53120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (item != null) {
53220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
53320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                onSubMenuSelected(subMenu);
53420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
53520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
536bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
537bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
538bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    @Override
53920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    public void onSubUiVisibilityChanged(boolean isVisible) {
54020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (isVisible) {
54120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            // Not a submenu, but treat it like one.
54220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            super.onSubMenuSelected(null);
54320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        } else {
54420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mMenu.close(false);
54520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
546bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
547bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
54849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void setMenuView(ActionMenuView menuView) {
54949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mMenuView = menuView;
55049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        menuView.initialize(mMenu);
55149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
552bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
55349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private static class SavedState implements Parcelable {
55420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public int openSubMenuId;
555bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
55620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        SavedState() {
55720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
558bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
55920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        SavedState(Parcel in) {
56020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            openSubMenuId = in.readInt();
56120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
56220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
56320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        @Override
56420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public int describeContents() {
56520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return 0;
56620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
567bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
56820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        @Override
56920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public void writeToParcel(Parcel dest, int flags) {
57020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            dest.writeInt(openSubMenuId);
571bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
57220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
57320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public static final Parcelable.Creator<SavedState> CREATOR
57420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                = new Parcelable.Creator<SavedState>() {
57520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            public SavedState createFromParcel(Parcel in) {
57620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                return new SavedState(in);
57720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
57820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
57920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            public SavedState[] newArray(int size) {
58020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                return new SavedState[size];
58120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
58220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        };
583bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
584bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
58549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private class OverflowMenuButton extends ImageButton implements ActionMenuView.ActionMenuChildView {
58620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public OverflowMenuButton(Context context) {
58720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            super(context, null, R.attr.actionOverflowButtonStyle);
58820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
58920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            setClickable(true);
59020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            setFocusable(true);
59120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            setVisibility(VISIBLE);
59220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            setEnabled(true);
59349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            setOnTouchListener(new ListPopupWindow.ForwardingListener(this) {
59449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                @Override
59549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                public ListPopupWindow getPopup() {
59649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    if (mOverflowPopup == null) {
59749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                        return null;
59849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    }
59949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
60049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    return mOverflowPopup.getPopup();
60149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                }
60249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
60349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                @Override
60449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                public boolean onForwardingStarted() {
60549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    showOverflowMenu();
60649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    return true;
60749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                }
60849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
60949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                @Override
61049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                public boolean onForwardingStopped() {
61149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    // Displaying the popup occurs asynchronously, so wait for
61249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    // the runnable to finish before deciding whether to stop
61349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    // forwarding.
61449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    if (mPostedOpenRunnable != null) {
61549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                        return false;
61649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    }
61749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
61849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    hideOverflowMenu();
61949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    return true;
62049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                }
62149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            });
62220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
62320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
62420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        @Override
62520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public boolean performClick() {
62620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (super.performClick()) {
62720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                return true;
62820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
62920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
63020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            playSoundEffect(SoundEffectConstants.CLICK);
63120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            showOverflowMenu();
63220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return true;
63320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
63420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
63549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
63620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public boolean needsDividerBefore() {
63720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return false;
63820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
63920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
64049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
64120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public boolean needsDividerAfter() {
64220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return false;
64320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
644ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
645ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        @Override
646ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
647ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            super.onLayout(changed, left, top, right, bottom);
648ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
649ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            // Set up the hotspot bounds to be centered on the image.
650ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            final Drawable d = getDrawable();
651ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            final Drawable bg = getBackground();
652ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            if (d != null && bg != null) {
653ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                final Rect bounds = d.getBounds();
654ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                final int height = bottom - top;
655ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                final int offset = (height - bounds.width()) / 2;
656ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                final int hotspotLeft = bounds.left - offset;
657ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                final int hotspotRight = bounds.right + offset;
658ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                DrawableCompat.setHotspotBounds(bg, hotspotLeft, 0, hotspotRight, height);
659ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            }
660ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        }
661bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
662bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
66320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private class OverflowPopup extends MenuPopupHelper {
664bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
66520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
66620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                boolean overflowOnly) {
66749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            super(context, menu, anchorView, overflowOnly, R.attr.actionOverflowMenuStyle);
66849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            setGravity(GravityCompat.END);
66920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            setCallback(mPopupPresenterCallback);
67020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
671bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
67220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        @Override
67320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public void onDismiss() {
67420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            super.onDismiss();
67520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mMenu.close();
67620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mOverflowPopup = null;
67720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
678bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
679bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
68049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private class ActionButtonSubmenu extends MenuPopupHelper {
68149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        private SubMenuBuilder mSubMenu;
68249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
68349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) {
68449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            super(context, subMenu, null, false,
68549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    R.attr.actionOverflowMenuStyle);
68649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            mSubMenu = subMenu;
68749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
68849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            MenuItemImpl item = (MenuItemImpl) subMenu.getItem();
68949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (!item.isActionButton()) {
69049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                // Give a reasonable anchor to nested submenus.
69149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
69249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
69320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
69420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            setCallback(mPopupPresenterCallback);
69549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
69649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            boolean preserveIconSpacing = false;
69749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final int count = subMenu.size();
69849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            for (int i = 0; i < count; i++) {
69949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                MenuItem childItem = subMenu.getItem(i);
70049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (childItem.isVisible() && childItem.getIcon() != null) {
70149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    preserveIconSpacing = true;
70249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    break;
70349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                }
70449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
70549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            setForceShowIcon(preserveIconSpacing);
70620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
70720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
70820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        @Override
70949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public void onDismiss() {
71049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            super.onDismiss();
71120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mActionButtonPopup = null;
71220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mOpenSubMenuId = 0;
71320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
714bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
715bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
71649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private class PopupPresenterCallback implements Callback {
71720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
71820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        @Override
71920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public boolean onOpenSubMenu(MenuBuilder subMenu) {
72049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (subMenu == null) return false;
72120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
72220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
72349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final Callback cb = getCallback();
72449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            return cb != null ? cb.onOpenSubMenu(subMenu) : false;
72520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
726bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
72720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        @Override
72820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
72920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (menu instanceof SubMenuBuilder) {
73020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                ((SubMenuBuilder) menu).getRootMenu().close(false);
73120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
73249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final Callback cb = getCallback();
73349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (cb != null) {
73449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                cb.onCloseMenu(menu, allMenusAreClosing);
73549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
73620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
737bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
738bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
73920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private class OpenOverflowRunnable implements Runnable {
74020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        private OverflowPopup mPopup;
74120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
74220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public OpenOverflowRunnable(OverflowPopup popup) {
74320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mPopup = popup;
74420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
74520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
74620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        public void run() {
74720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mMenu.changeMenuMode();
74820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final View menuView = (View) mMenuView;
74920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (menuView != null && menuView.getWindowToken() != null && mPopup.tryShow()) {
75020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mOverflowPopup = mPopup;
75120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
75220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mPostedOpenRunnable = null;
75320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
754bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
75549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
75649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private class ActionMenuPopupCallback extends ActionMenuItemView.PopupCallback {
75749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
75849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public ListPopupWindow getPopup() {
75949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null;
76049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
76149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
762bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell}
763