1696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell/*
2696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Copyright (C) 2011 The Android Open Source Project
3696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell *
4696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
5696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * you may not use this file except in compliance with the License.
6696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * You may obtain a copy of the License at
7696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell *
8696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
9696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell *
10696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Unless required by applicable law or agreed to in writing, software
11696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
12696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * See the License for the specific language governing permissions and
14696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * limitations under the License.
15696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell */
16696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
17fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellpackage android.widget;
18696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
19696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.content.Context;
20bfcdfaf919cdb67897a6e24afc8f14b2c810596aAdam Powellimport android.content.res.Configuration;
21696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.content.res.Resources;
229d9581f52edcbd086edcd4153e9daa29c0205256Alan Viveretteimport android.graphics.Matrix;
23f023c2530a4591889dda614aaa016d5a9f9617edAlan Viveretteimport android.graphics.Rect;
24f023c2530a4591889dda614aaa016d5a9f9617edAlan Viveretteimport android.graphics.drawable.Drawable;
2511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powellimport android.os.Parcel;
2611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powellimport android.os.Parcelable;
27696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.util.SparseBooleanArray;
28823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powellimport android.view.ActionProvider;
2954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powellimport android.view.Gravity;
30696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.view.MenuItem;
31696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.view.SoundEffectConstants;
32696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.view.View;
33696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.view.View.MeasureSpec;
34696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.view.ViewGroup;
35ad79b90f21dcde6f741c47a251882c0a47c5f698Adam Powellimport android.view.accessibility.AccessibilityNodeInfo;
36ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viveretteimport android.widget.ListPopupWindow.ForwardingListener;
37ad79b90f21dcde6f741c47a251882c0a47c5f698Adam Powellimport com.android.internal.transition.ActionBarTransition;
3880e72700858eb58b379f77a0da5fd3a98e1aa07cAlan Viveretteimport com.android.internal.view.ActionBarPolicy;
39fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.ActionMenuItemView;
40fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.BaseMenuPresenter;
41fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.MenuBuilder;
42fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.MenuItemImpl;
43fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.MenuPopupHelper;
44fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.MenuView;
45fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.SubMenuBuilder;
46696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
47696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport java.util.ArrayList;
48696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
49696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell/**
50696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * MenuPresenter for building action menus as seen in the action bar and action modes.
51fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell *
52fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * @hide
53696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell */
54823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powellpublic class ActionMenuPresenter extends BaseMenuPresenter
55823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell        implements ActionProvider.SubUiVisibilityListener {
56640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    private static final String TAG = "ActionMenuPresenter";
57640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
58696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private View mOverflowButton;
59696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private boolean mReserveOverflow;
601ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell    private boolean mReserveOverflowSet;
61696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private int mWidthLimit;
62696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private int mActionItemWidthLimit;
63696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private int mMaxItems;
641ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell    private boolean mMaxItemsSet;
65640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    private boolean mStrictWidthLimit;
661ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell    private boolean mWidthLimitSet;
67b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell    private boolean mExpandedActionViewsExclusive;
68696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
6935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    private int mMinCellSize;
7035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
71696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    // Group IDs that have been added as actions - used temporarily, allocated here for reuse.
72696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray();
73696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
74696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private View mScrapActionButtonView;
75696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
76696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private OverflowPopup mOverflowPopup;
77696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private ActionButtonSubmenu mActionButtonPopup;
78696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
79696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private OpenOverflowRunnable mPostedOpenRunnable;
8056110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette    private ActionMenuPopupCallback mPopupCallback;
81696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
8211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
8311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    int mOpenSubMenuId;
8411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
85538e565c06e915b91e7e3a901f872ccdd9bccdd3Adam Powell    public ActionMenuPresenter(Context context) {
86538e565c06e915b91e7e3a901f872ccdd9bccdd3Adam Powell        super(context, com.android.internal.R.layout.action_menu_layout,
87696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                com.android.internal.R.layout.action_menu_item_layout);
88696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
89696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
90696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
91696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void initForMenu(Context context, MenuBuilder menu) {
92696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        super.initForMenu(context, menu);
93696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
94696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final Resources res = context.getResources();
951ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell
96b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell        final ActionBarPolicy abp = ActionBarPolicy.get(context);
971ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        if (!mReserveOverflowSet) {
98b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell            mReserveOverflow = abp.showsOverflowMenuButton();
991ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        }
1001ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell
1011ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        if (!mWidthLimitSet) {
102b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell            mWidthLimit = abp.getEmbeddedMenuWidthLimit();
1031ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        }
104696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
105696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        // Measure for initial configuration
1061ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        if (!mMaxItemsSet) {
107b8139af3dcae80c0030afd0354dc424a7c72c3d9Adam Powell            mMaxItems = abp.getMaxActionButtons();
1081ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        }
109696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
110696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        int width = mWidthLimit;
111696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mReserveOverflow) {
1129b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell            if (mOverflowButton == null) {
113538e565c06e915b91e7e3a901f872ccdd9bccdd3Adam Powell                mOverflowButton = new OverflowMenuButton(mSystemContext);
1149b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell                final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
1159b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell                mOverflowButton.measure(spec, spec);
1169b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell            }
117696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            width -= mOverflowButton.getMeasuredWidth();
118696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        } else {
119696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mOverflowButton = null;
120696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
121696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
122696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mActionItemWidthLimit = width;
123696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
12435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        mMinCellSize = (int) (ActionMenuView.MIN_CELL_SIZE * res.getDisplayMetrics().density);
12535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
126696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        // Drop a scrap view as it may no longer reflect the proper context/config.
127696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mScrapActionButtonView = null;
128696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
129696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
130bfcdfaf919cdb67897a6e24afc8f14b2c810596aAdam Powell    public void onConfigurationChanged(Configuration newConfig) {
131bfcdfaf919cdb67897a6e24afc8f14b2c810596aAdam Powell        if (!mMaxItemsSet) {
132bfcdfaf919cdb67897a6e24afc8f14b2c810596aAdam Powell            mMaxItems = mContext.getResources().getInteger(
133bfcdfaf919cdb67897a6e24afc8f14b2c810596aAdam Powell                    com.android.internal.R.integer.max_action_buttons);
134f203e0a44ef7578c080d63424820fb5a94a4e92fAdam Powell        }
135f203e0a44ef7578c080d63424820fb5a94a4e92fAdam Powell        if (mMenu != null) {
136f203e0a44ef7578c080d63424820fb5a94a4e92fAdam Powell            mMenu.onItemsChanged(true);
137bfcdfaf919cdb67897a6e24afc8f14b2c810596aAdam Powell        }
138bfcdfaf919cdb67897a6e24afc8f14b2c810596aAdam Powell    }
139bfcdfaf919cdb67897a6e24afc8f14b2c810596aAdam Powell
140640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public void setWidthLimit(int width, boolean strict) {
1411ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        mWidthLimit = width;
142640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        mStrictWidthLimit = strict;
1431ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        mWidthLimitSet = true;
1441ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell    }
1451ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell
1461ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell    public void setReserveOverflow(boolean reserveOverflow) {
1471ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        mReserveOverflow = reserveOverflow;
1481ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        mReserveOverflowSet = true;
1499b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell    }
1509b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell
1519b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell    public void setItemLimit(int itemCount) {
1529b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell        mMaxItems = itemCount;
1531ab418a222e1834c4b1312fde355e41a1947af0dAdam Powell        mMaxItemsSet = true;
1549b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell    }
1559b4bee0f14bbd137b0797127aff2df46a6321ec5Adam Powell
156b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell    public void setExpandedActionViewsExclusive(boolean isExclusive) {
157b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell        mExpandedActionViewsExclusive = isExclusive;
158b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell    }
159b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell
160696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
161696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public MenuView getMenuView(ViewGroup root) {
162696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        MenuView result = super.getMenuView(root);
163696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        ((ActionMenuView) result).setPresenter(this);
164696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return result;
165696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
166696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
167696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
168fbe4a586c29b6e415e8d39d73d19bd7f0215a851Alan Viverette    public View getItemView(final MenuItemImpl item, View convertView, ViewGroup parent) {
1698d02deabac62c4a68a335a7b3141795466362b89Adam Powell        View actionView = item.getActionView();
17035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        if (actionView == null || item.hasCollapsibleActionView()) {
171c3ca3ea3a937a20666e4f01fb1a9efb503ec274eAdam Powell            actionView = super.getItemView(item, convertView, parent);
17235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
1738d02deabac62c4a68a335a7b3141795466362b89Adam Powell        actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
17435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
175efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        final ActionMenuView menuParent = (ActionMenuView) parent;
176efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
177efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        if (!menuParent.checkLayoutParams(lp)) {
178efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell            actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
179efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        }
180efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        return actionView;
181efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell    }
182efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell
183efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell    @Override
18456110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette    public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) {
185efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        itemView.initialize(item, 0);
186efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell
187efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        final ActionMenuView menuView = (ActionMenuView) mMenuView;
188efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
189efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell        actionItemView.setItemInvoker(menuView);
190efc3bb06127a6640afe4985b2b2fc03c5ecc5deeAdam Powell
19156110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette        if (mPopupCallback == null) {
19256110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette            mPopupCallback = new ActionMenuPopupCallback();
193fbe4a586c29b6e415e8d39d73d19bd7f0215a851Alan Viverette        }
19456110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette        actionItemView.setPopupCallback(mPopupCallback);
195696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
196696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
197696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
198696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) {
199696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return item.isActionButton();
200696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
201696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
202696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
203696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void updateMenuView(boolean cleared) {
204ad79b90f21dcde6f741c47a251882c0a47c5f698Adam Powell        final ViewGroup menuViewParent = (ViewGroup) ((View) mMenuView).getParent();
205ad79b90f21dcde6f741c47a251882c0a47c5f698Adam Powell        if (menuViewParent != null) {
206d8d7c38533d20062166e5e7ef89b80ff9dbd8903Chet Haase            ActionBarTransition.beginDelayedTransition(menuViewParent);
207ad79b90f21dcde6f741c47a251882c0a47c5f698Adam Powell        }
208696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        super.updateMenuView(cleared);
209696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
210da9710806bc7874b8c553f4daf9cf14f35ae1b07Adam Powell        ((View) mMenuView).requestLayout();
211da9710806bc7874b8c553f4daf9cf14f35ae1b07Adam Powell
212823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell        if (mMenu != null) {
213823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            final ArrayList<MenuItemImpl> actionItems = mMenu.getActionItems();
214823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            final int count = actionItems.size();
215823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            for (int i = 0; i < count; i++) {
216823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                final ActionProvider provider = actionItems.get(i).getActionProvider();
217823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                if (provider != null) {
218823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                    provider.setSubUiVisibilityListener(this);
219823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                }
220823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            }
221823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell        }
222823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell
223275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        final ArrayList<MenuItemImpl> nonActionItems = mMenu != null ?
224275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                mMenu.getNonActionItems() : null;
225275702c2f47ed87ab642462530092d9777f32ecdAdam Powell
226275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        boolean hasOverflow = false;
227275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        if (mReserveOverflow && nonActionItems != null) {
228275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            final int count = nonActionItems.size();
229275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            if (count == 1) {
230275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                hasOverflow = !nonActionItems.get(0).isActionViewExpanded();
231275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            } else {
232275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                hasOverflow = count > 0;
233275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            }
234275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        }
235275702c2f47ed87ab642462530092d9777f32ecdAdam Powell
23614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        if (hasOverflow) {
237696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (mOverflowButton == null) {
238538e565c06e915b91e7e3a901f872ccdd9bccdd3Adam Powell                mOverflowButton = new OverflowMenuButton(mSystemContext);
239696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
240696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            ViewGroup parent = (ViewGroup) mOverflowButton.getParent();
241696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (parent != mMenuView) {
242696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                if (parent != null) {
243696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    parent.removeView(mOverflowButton);
244696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                }
24535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                ActionMenuView menuView = (ActionMenuView) mMenuView;
24635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                menuView.addView(mOverflowButton, menuView.generateOverflowButtonLayoutParams());
247696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
248696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        } else if (mOverflowButton != null && mOverflowButton.getParent() == mMenuView) {
249696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            ((ViewGroup) mMenuView).removeView(mOverflowButton);
250696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
25114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
25214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        ((ActionMenuView) mMenuView).setOverflowReserved(mReserveOverflow);
253696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
254696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
255696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
256696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean filterLeftoverView(ViewGroup parent, int childIndex) {
257696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (parent.getChildAt(childIndex) == mOverflowButton) return false;
258696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return super.filterLeftoverView(parent, childIndex);
259696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
260696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
261696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
262696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (!subMenu.hasVisibleItems()) return false;
263696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
264696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        SubMenuBuilder topSubMenu = subMenu;
265696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        while (topSubMenu.getParentMenu() != mMenu) {
266696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu();
267696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
268696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        View anchor = findViewForItem(topSubMenu.getItem());
26911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        if (anchor == null) {
27011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            if (mOverflowButton == null) return false;
27111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            anchor = mOverflowButton;
27211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
273696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
27411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        mOpenSubMenuId = subMenu.getItem().getItemId();
275696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu);
276696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mActionButtonPopup.setAnchorView(anchor);
277696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mActionButtonPopup.show();
278696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        super.onSubMenuSelected(subMenu);
279696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return true;
280696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
281696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
282696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private View findViewForItem(MenuItem item) {
283696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final ViewGroup parent = (ViewGroup) mMenuView;
284696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (parent == null) return null;
285696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
286696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final int count = parent.getChildCount();
287696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (int i = 0; i < count; i++) {
288696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final View child = parent.getChildAt(i);
289696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (child instanceof MenuView.ItemView &&
290696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    ((MenuView.ItemView) child).getItemData() == item) {
291696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                return child;
292696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
293696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
294696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return null;
295696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
296696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
297696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
298696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Display the overflow menu if one is present.
299696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @return true if the overflow menu was shown, false otherwise.
300696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
301696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean showOverflowMenu() {
30270e9f4bd2c044858f3c1c040ffce973351a2383aAdam Powell        if (mReserveOverflow && !isOverflowMenuShowing() && mMenu != null && mMenuView != null &&
303a647640f85f415bd8fb8cb925e7687658fe9ae37Jake Wharton                mPostedOpenRunnable == null && !mMenu.getNonActionItems().isEmpty()) {
304696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            OverflowPopup popup = new OverflowPopup(mContext, mMenu, mOverflowButton, true);
305696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPostedOpenRunnable = new OpenOverflowRunnable(popup);
306696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            // Post this for later; we might still need a layout for the anchor to be right.
307696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            ((View) mMenuView).post(mPostedOpenRunnable);
308696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
309696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            // ActionMenuPresenter uses null as a callback argument here
310696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            // to indicate overflow is opening.
311696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            super.onSubMenuSelected(null);
312696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
313696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return true;
314696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
315696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return false;
316696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
317696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
318696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
319696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Hide the overflow menu if it is currently showing.
320696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     *
321696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @return true if the overflow menu was hidden, false otherwise.
322696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
323696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean hideOverflowMenu() {
324696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mPostedOpenRunnable != null && mMenuView != null) {
325696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            ((View) mMenuView).removeCallbacks(mPostedOpenRunnable);
326678ed0c5a32bac1ea18a5ac99b0b814421ea79b4Adam Powell            mPostedOpenRunnable = null;
327696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return true;
328696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
329696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
330696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        MenuPopupHelper popup = mOverflowPopup;
331696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (popup != null) {
332696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            popup.dismiss();
333696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return true;
334696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
335696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return false;
336696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
337696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
338696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
339696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Dismiss all popup menus - overflow and submenus.
340696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @return true if popups were dismissed, false otherwise. (This can be because none were open.)
341696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
342696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean dismissPopupMenus() {
343696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        boolean result = hideOverflowMenu();
344696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        result |= hideSubMenus();
345696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return result;
346696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
347696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
348696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
349696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Dismiss all submenu popups.
350696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     *
351696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @return true if popups were dismissed, false otherwise. (This can be because none were open.)
352696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
353696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean hideSubMenus() {
354696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mActionButtonPopup != null) {
355696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mActionButtonPopup.dismiss();
356696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return true;
357696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
358696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return false;
359696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
360696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
361696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
362696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @return true if the overflow menu is currently showing
363696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
364696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean isOverflowMenuShowing() {
365696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return mOverflowPopup != null && mOverflowPopup.isShowing();
366696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
367696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
3685fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell    public boolean isOverflowMenuShowPending() {
3695fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell        return mPostedOpenRunnable != null || isOverflowMenuShowing();
3705fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell    }
3715fcf5b9fd3ff6757090c6bd166b60c18eda0b3efAdam Powell
372696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
373696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @return true if space has been reserved in the action menu for an overflow item.
374696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
375696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean isOverflowReserved() {
376696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return mReserveOverflow;
377696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
378696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
379696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean flagActionItems() {
380696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems();
381696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final int itemsSize = visibleItems.size();
382696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        int maxActions = mMaxItems;
383696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        int widthLimit = mActionItemWidthLimit;
384696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
385696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final ViewGroup parent = (ViewGroup) mMenuView;
386696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
387696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        int requiredItems = 0;
388696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        int requestedItems = 0;
389696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        int firstActionWidth = 0;
390696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        boolean hasOverflow = false;
391696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (int i = 0; i < itemsSize; i++) {
392696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            MenuItemImpl item = visibleItems.get(i);
393696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (item.requiresActionButton()) {
394696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                requiredItems++;
395696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            } else if (item.requestsActionButton()) {
396696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                requestedItems++;
397696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            } else {
398696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                hasOverflow = true;
399696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
400b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell            if (mExpandedActionViewsExclusive && item.isActionViewExpanded()) {
401b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell                // Overflow everything if we have an expanded action view and we're
402b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell                // space constrained.
403b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell                maxActions = 0;
404b187cd9c54f0100c0fb47c354cdecad29ca7c0aeAdam Powell            }
405696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
406696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
407696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        // Reserve a spot for the overflow item if needed.
408696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mReserveOverflow &&
409696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                (hasOverflow || requiredItems + requestedItems > maxActions)) {
410696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            maxActions--;
411696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
412696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        maxActions -= requiredItems;
413696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
414696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final SparseBooleanArray seenGroups = mActionButtonGroups;
415696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        seenGroups.clear();
416696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
41735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int cellSize = 0;
41835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int cellsRemaining = 0;
41935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        if (mStrictWidthLimit) {
42035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsRemaining = widthLimit / mMinCellSize;
42135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int cellSizeRemaining = widthLimit % mMinCellSize;
42235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellSize = mMinCellSize + cellSizeRemaining / cellsRemaining;
42335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
42435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
425696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        // Flag as many more requested items as will fit.
426696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (int i = 0; i < itemsSize; i++) {
427696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            MenuItemImpl item = visibleItems.get(i);
428696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
429696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (item.requiresActionButton()) {
43035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                View v = getItemView(item, mScrapActionButtonView, parent);
43135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                if (mScrapActionButtonView == null) {
43235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    mScrapActionButtonView = v;
43335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                }
43435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                if (mStrictWidthLimit) {
43535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    cellsRemaining -= ActionMenuView.measureChildForCells(v,
43635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                            cellSize, cellsRemaining, querySpec, 0);
43735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                } else {
43835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    v.measure(querySpec, querySpec);
439696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                }
440696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                final int measuredWidth = v.getMeasuredWidth();
441696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                widthLimit -= measuredWidth;
442696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                if (firstActionWidth == 0) {
443696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    firstActionWidth = measuredWidth;
444696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                }
445696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                final int groupId = item.getGroupId();
446696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                if (groupId != 0) {
447696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    seenGroups.put(groupId, true);
448696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                }
449ea1ca952c625d51dc71e1cc3d955b239921888c7Adam Powell                item.setIsActionButton(true);
450696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            } else if (item.requestsActionButton()) {
451696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                // Items in a group with other items that already have an action slot
452696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                // can break the max actions rule, but not the width limit.
453696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                final int groupId = item.getGroupId();
454696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                final boolean inGroup = seenGroups.get(groupId);
45535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0 &&
45635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                        (!mStrictWidthLimit || cellsRemaining > 0);
457696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
458696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                if (isAction) {
45935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    View v = getItemView(item, mScrapActionButtonView, parent);
46035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    if (mScrapActionButtonView == null) {
46135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                        mScrapActionButtonView = v;
46235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    }
46335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    if (mStrictWidthLimit) {
46435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                        final int cells = ActionMenuView.measureChildForCells(v,
46535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                                cellSize, cellsRemaining, querySpec, 0);
46635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                        cellsRemaining -= cells;
46735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                        if (cells == 0) {
46835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                            isAction = false;
469696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                        }
47035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    } else {
47135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                        v.measure(querySpec, querySpec);
472696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    }
473696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    final int measuredWidth = v.getMeasuredWidth();
474696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    widthLimit -= measuredWidth;
475696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    if (firstActionWidth == 0) {
476696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                        firstActionWidth = measuredWidth;
477696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    }
478696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
479640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    if (mStrictWidthLimit) {
48035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                        isAction &= widthLimit >= 0;
481640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    } else {
482640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                        // Did this push the entire first item past the limit?
48335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                        isAction &= widthLimit + firstActionWidth > 0;
484696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    }
485696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                }
486696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
487696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                if (isAction && groupId != 0) {
488696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    seenGroups.put(groupId, true);
489696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                } else if (inGroup) {
490696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    // We broke the width limit. Demote the whole group, they all overflow now.
491696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    seenGroups.put(groupId, false);
492696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    for (int j = 0; j < i; j++) {
493696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                        MenuItemImpl areYouMyGroupie = visibleItems.get(j);
494696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                        if (areYouMyGroupie.getGroupId() == groupId) {
49523f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell                            // Give back the action slot
49623f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell                            if (areYouMyGroupie.isActionButton()) maxActions++;
497696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                            areYouMyGroupie.setIsActionButton(false);
498696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                        }
499696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    }
500696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                }
501696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
50223f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell                if (isAction) maxActions--;
50323f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell
504696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                item.setIsActionButton(isAction);
50514c4669916ae993b248f00c55daf0f17069903d9Svetoslav Ganov            } else {
50614c4669916ae993b248f00c55daf0f17069903d9Svetoslav Ganov                // Neither requires nor requests an action button.
50714c4669916ae993b248f00c55daf0f17069903d9Svetoslav Ganov                item.setIsActionButton(false);
508696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
509696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
510696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return true;
511696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
512696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
513696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
514696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
515696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        dismissPopupMenus();
516696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        super.onCloseMenu(menu, allMenusAreClosing);
517696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
518696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
51911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    @Override
52011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    public Parcelable onSaveInstanceState() {
52111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        SavedState state = new SavedState();
52211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        state.openSubMenuId = mOpenSubMenuId;
52311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        return state;
52411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
52511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
52611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    @Override
52711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    public void onRestoreInstanceState(Parcelable state) {
52811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        SavedState saved = (SavedState) state;
52911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        if (saved.openSubMenuId > 0) {
53011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            MenuItem item = mMenu.findItem(saved.openSubMenuId);
53111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            if (item != null) {
53211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
53311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                onSubMenuSelected(subMenu);
53411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            }
53511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
53611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
53711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
538823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell    @Override
539823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell    public void onSubUiVisibilityChanged(boolean isVisible) {
540823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell        if (isVisible) {
541823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            // Not a submenu, but treat it like one.
542823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            super.onSubMenuSelected(null);
543823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell        } else {
544823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            mMenu.close(false);
545823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell        }
546823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell    }
547823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell
548fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    public void setMenuView(ActionMenuView menuView) {
549fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        mMenuView = menuView;
550e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        menuView.initialize(mMenu);
551fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    }
552fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
55311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    private static class SavedState implements Parcelable {
55411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        public int openSubMenuId;
55511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
55611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        SavedState() {
55711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
55811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
55911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        SavedState(Parcel in) {
56011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            openSubMenuId = in.readInt();
56111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
56211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
56311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        @Override
56411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        public int describeContents() {
56511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            return 0;
56611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
56711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
56811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        @Override
56911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        public void writeToParcel(Parcel dest, int flags) {
57011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            dest.writeInt(openSubMenuId);
57111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
57211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
57311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        public static final Parcelable.Creator<SavedState> CREATOR
57411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                = new Parcelable.Creator<SavedState>() {
57511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            public SavedState createFromParcel(Parcel in) {
57611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                return new SavedState(in);
57711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            }
57811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
57911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            public SavedState[] newArray(int size) {
58011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                return new SavedState[size];
58111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            }
58211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        };
58311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
58411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
585fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    private class OverflowMenuButton extends ImageButton implements ActionMenuView.ActionMenuChildView {
5869d9581f52edcbd086edcd4153e9daa29c0205256Alan Viverette        private final float[] mTempPts = new float[2];
5879d9581f52edcbd086edcd4153e9daa29c0205256Alan Viverette
588696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public OverflowMenuButton(Context context) {
589696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
590696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
591696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            setClickable(true);
592696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            setFocusable(true);
593696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            setVisibility(VISIBLE);
594696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            setEnabled(true);
595ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
59669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            setOnTouchListener(new ForwardingListener(this) {
597ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                @Override
598ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                public ListPopupWindow getPopup() {
599ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    if (mOverflowPopup == null) {
600ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                        return null;
601ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    }
602ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
603ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    return mOverflowPopup.getPopup();
604ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                }
605ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
606ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                @Override
607ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                public boolean onForwardingStarted() {
608ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    showOverflowMenu();
609ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    return true;
610ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                }
611ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
612ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                @Override
613ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                public boolean onForwardingStopped() {
614ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    // Displaying the popup occurs asynchronously, so wait for
615ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    // the runnable to finish before deciding whether to stop
616ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    // forwarding.
617ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    if (mPostedOpenRunnable != null) {
618ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                        return false;
619ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    }
620ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
621ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    hideOverflowMenu();
622ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                    return true;
623ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                }
624ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            });
625696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
626696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
627696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        @Override
628696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean performClick() {
629696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (super.performClick()) {
630696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                return true;
631696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
632696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
633696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            playSoundEffect(SoundEffectConstants.CLICK);
634696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            showOverflowMenu();
635696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return true;
636696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
637696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
63880e72700858eb58b379f77a0da5fd3a98e1aa07cAlan Viverette        @Override
639696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean needsDividerBefore() {
64035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            return false;
641696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
642696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
64380e72700858eb58b379f77a0da5fd3a98e1aa07cAlan Viverette        @Override
644696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean needsDividerAfter() {
645696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return false;
646696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
647d5c81db1e78e98f3e0a1a5cf206865c3056294c4Adam Powell
648d5c81db1e78e98f3e0a1a5cf206865c3056294c4Adam Powell        @Override
649058ac7cfe5bb7b9ecc411b94622ac3f31a7fa25eAlan Viverette        public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
650058ac7cfe5bb7b9ecc411b94622ac3f31a7fa25eAlan Viverette            super.onInitializeAccessibilityNodeInfo(info);
651cb8ed39b3fb591be60b9fb1799d4ea4530eab758Svetoslav Ganov            info.setCanOpenPopup(true);
652058ac7cfe5bb7b9ecc411b94622ac3f31a7fa25eAlan Viverette        }
653f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette
654f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette        @Override
6559d9581f52edcbd086edcd4153e9daa29c0205256Alan Viverette        protected boolean setFrame(int l, int t, int r, int b) {
6569d9581f52edcbd086edcd4153e9daa29c0205256Alan Viverette            final boolean changed = super.setFrame(l, t, r, b);
657f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette
658199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette            // Set up the hotspot bounds to square and centered on the image.
659f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette            final Drawable d = getDrawable();
660f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette            final Drawable bg = getBackground();
661f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette            if (d != null && bg != null) {
662199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                final int width = getWidth();
663199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                final int height = getHeight();
664199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                final int halfEdge = Math.max(width, height) / 2;
665199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                final int offsetX = getPaddingLeft() - getPaddingRight();
666199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                final int offsetY = getPaddingTop() - getPaddingBottom();
667199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                final int centerX = (width + offsetX) / 2;
668199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                final int centerY = (height + offsetY) / 2;
669199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                bg.setHotspotBounds(centerX - halfEdge, centerY - halfEdge,
670199ea8c0c759d5993b23467f22f2bff120c93d38Alan Viverette                        centerX + halfEdge, centerY + halfEdge);
671f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette            }
6729d9581f52edcbd086edcd4153e9daa29c0205256Alan Viverette
6739d9581f52edcbd086edcd4153e9daa29c0205256Alan Viverette            return changed;
674f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette        }
675696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
676696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
677696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private class OverflowPopup extends MenuPopupHelper {
678696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
679696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                boolean overflowOnly) {
680560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            super(context, menu, anchorView, overflowOnly,
681560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                    com.android.internal.R.attr.actionOverflowMenuStyle);
68254c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell            setGravity(Gravity.END);
68311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            setCallback(mPopupPresenterCallback);
684696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
685696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
686696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        @Override
687696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public void onDismiss() {
688696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            super.onDismiss();
689696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mMenu.close();
690696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mOverflowPopup = null;
691696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
692696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
693696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
694696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private class ActionButtonSubmenu extends MenuPopupHelper {
695696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        private SubMenuBuilder mSubMenu;
696696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
697696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) {
698d361a4f98bbc03cb61b9ac4504eda490ff704b60Alan Viverette            super(context, subMenu, null, false,
699d361a4f98bbc03cb61b9ac4504eda490ff704b60Alan Viverette                    com.android.internal.R.attr.actionOverflowMenuStyle);
700696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mSubMenu = subMenu;
701696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
702696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            MenuItemImpl item = (MenuItemImpl) subMenu.getItem();
703696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (!item.isActionButton()) {
704696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                // Give a reasonable anchor to nested submenus.
705696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
706696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
70711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
70811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            setCallback(mPopupPresenterCallback);
7099151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell
7109151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            boolean preserveIconSpacing = false;
7119151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            final int count = subMenu.size();
7129151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            for (int i = 0; i < count; i++) {
7139151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                MenuItem childItem = subMenu.getItem(i);
7149151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                if (childItem.isVisible() && childItem.getIcon() != null) {
7159151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                    preserveIconSpacing = true;
7169151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                    break;
7179151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                }
7189151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            }
7199151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            setForceShowIcon(preserveIconSpacing);
720696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
721696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
722696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        @Override
723696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public void onDismiss() {
724696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            super.onDismiss();
725696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mActionButtonPopup = null;
72611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            mOpenSubMenuId = 0;
72711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
72811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
72911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
730fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    private class PopupPresenterCallback implements Callback {
73111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
73211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        @Override
73311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        public boolean onOpenSubMenu(MenuBuilder subMenu) {
734823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            if (subMenu == null) return false;
735823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell
73611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
737fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            final Callback cb = getCallback();
738b411b32861e7794a59fa7558dbe9d97407eccf23Adam Powell            return cb != null ? cb.onOpenSubMenu(subMenu) : false;
73911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
74011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
74111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        @Override
74211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
743823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            if (menu instanceof SubMenuBuilder) {
744823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                ((SubMenuBuilder) menu).getRootMenu().close(false);
745823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            }
746fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            final Callback cb = getCallback();
747b411b32861e7794a59fa7558dbe9d97407eccf23Adam Powell            if (cb != null) {
748b411b32861e7794a59fa7558dbe9d97407eccf23Adam Powell                cb.onCloseMenu(menu, allMenusAreClosing);
749b411b32861e7794a59fa7558dbe9d97407eccf23Adam Powell            }
750696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
751696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
752696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
753696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private class OpenOverflowRunnable implements Runnable {
754696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        private OverflowPopup mPopup;
755696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
756696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public OpenOverflowRunnable(OverflowPopup popup) {
757696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPopup = popup;
758696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
759696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
760696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public void run() {
761696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mMenu.changeMenuMode();
762678ed0c5a32bac1ea18a5ac99b0b814421ea79b4Adam Powell            final View menuView = (View) mMenuView;
763678ed0c5a32bac1ea18a5ac99b0b814421ea79b4Adam Powell            if (menuView != null && menuView.getWindowToken() != null && mPopup.tryShow()) {
764696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                mOverflowPopup = mPopup;
765696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
766678ed0c5a32bac1ea18a5ac99b0b814421ea79b4Adam Powell            mPostedOpenRunnable = null;
767696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
768696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
76956110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette
77056110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette    private class ActionMenuPopupCallback extends ActionMenuItemView.PopupCallback {
77156110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette        @Override
77256110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette        public ListPopupWindow getPopup() {
77356110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette            return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null;
77456110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette        }
77556110725f2a0b3f09703f2cbe9705d97609ee1e5Alan Viverette    }
776696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell}
777