149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes/*
249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2012 The Android Open Source Project
349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * you may not use this file except in compliance with the License.
649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * You may obtain a copy of the License at
749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
1049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Unless required by applicable law or agreed to in writing, software
1149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * See the License for the specific language governing permissions and
1449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * limitations under the License.
1549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */
16bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
17da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.view.menu;
18bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
19bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.ComponentName;
20bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Context;
21bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Intent;
22ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.pm.PackageManager;
23ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.pm.ResolveInfo;
24ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.res.Configuration;
25ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.res.Resources;
26bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.graphics.drawable.Drawable;
27ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.os.Bundle;
28ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.os.Parcelable;
297fa6a00a4600aac591402398c23fea97721adf26Chris Banesimport android.support.v4.content.ContextCompat;
3030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.view.MenuItemCompat;
31da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
3230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.view.ActionProvider;
3330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenu;
3430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenuItem;
35ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.util.SparseArray;
36ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.view.ContextMenu;
37ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.view.KeyCharacterMap;
38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.KeyEvent;
3930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
4030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.SubMenu;
41bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View;
42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
43ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.lang.ref.WeakReference;
44bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList;
45ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.util.List;
46ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.util.concurrent.CopyOnWriteArrayList;
47bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
48bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/**
4930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell * Implementation of the {@link android.support.v4.internal.view.SupportMenu} interface for creating a
50ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani * standard menu UI.
5189208232f3b5d1451408d787872504a190bc7ee0Chris Banes *
5289208232f3b5d1451408d787872504a190bc7ee0Chris Banes * @hide
53bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
5430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellpublic class MenuBuilder implements SupportMenu {
5520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
56ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String TAG = "MenuBuilder";
57ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String PRESENTER_KEY = "android:menu:presenters";
59ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
60ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview";
61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private static final int[] sCategoryToOrder = new int[]{
63ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            1, /* No category */
64ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            4, /* CONTAINER */
65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            5, /* SYSTEM */
66ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            3, /* SECONDARY */
67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            2, /* ALTERNATIVE */
68ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            0, /* SELECTED_ALTERNATIVE */
69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    };
70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
71ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Context mContext;
7220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
73ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Resources mResources;
74ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
75ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
7620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode() instead of accessing
7720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * this directly.
78ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
79ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mQwertyMode;
80ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
81ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
8220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether the shortcuts should be visible on menus. Use isShortcutsVisible() instead of
8320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * accessing this directly.
84ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
85ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mShortcutsVisible;
86ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
87ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
8820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Callback that will receive the various menu-related events generated by this class. Use
8920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * getCallback to get a reference to the callback.
90ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
91ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private Callback mCallback;
92ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
9420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Contains all of the items for this menu
9520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
96ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mItems;
97ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
9920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Contains only the items that are currently visible.  This will be created/refreshed from
10020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * {@link #getVisibleItems()}
10120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mVisibleItems;
10320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Whether or not the items (or any one item's shown state) has changed since it was last
106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * fetched from {@link #getVisibleItems()}
107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsVisibleItemsStale;
109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Contains only the items that should appear in the Action Bar, if present.
112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mActionItems;
11420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Contains items that should NOT appear in the Action Bar, if present.
117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mNonActionItems;
119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
12120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether or not the items (or any one item's action state) has changed since it was last
12220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * fetched.
123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsActionItemsStale;
125ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
127ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Default value for how added items should show in the action list.
128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
12930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    private int mDefaultShowAsAction = SupportMenuItem.SHOW_AS_ACTION_NEVER;
130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
13220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Current use case is Context Menus: As Views populate the context menu, each one has extra
13320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * information that should be passed along.  This is the current menu info that should be set on
13420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * all items added to this menu.
135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ContextMenu.ContextMenuInfo mCurrentMenuInfo;
137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
13820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
13920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header title for menu types that have a header (context and submenus)
14020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    CharSequence mHeaderTitle;
14220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
14320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
14420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header icon for menu types that have a header and support icons (context)
14520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Drawable mHeaderIcon;
14749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /** Header custom view for menu types that have a header and support custom views (context) */
14849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    View mHeaderView;
14920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
15020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
15149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Contains the state of the View hierarchy for all menu views when the menu
15249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * was frozen.
15320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
15449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private SparseArray<Parcelable> mFrozenViewStates;
155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
15749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Prevents onItemsChanged from doing its junk, useful for batching commands
15849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * that may individually call onItemsChanged.
159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mPreventDispatchingItemsChanged = false;
16120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mItemsChangedWhileDispatchPrevented = false;
163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mOptionalIconsVisible = false;
165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsClosing = false;
167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mTempShortcutItemList = new ArrayList<MenuItemImpl>();
169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private CopyOnWriteArrayList<WeakReference<MenuPresenter>> mPresenters =
171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            new CopyOnWriteArrayList<WeakReference<MenuPresenter>>();
172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Currently expanded menu item; must be collapsed when we clear.
175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuItemImpl mExpandedItem;
177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1794e411251159c965caccb3bf3727c2921d74f06c1Chris Banes     * Whether to override the result of {@link #hasVisibleItems()} and always return true
1804e411251159c965caccb3bf3727c2921d74f06c1Chris Banes     */
1814e411251159c965caccb3bf3727c2921d74f06c1Chris Banes    private boolean mOverrideVisibleItems;
1824e411251159c965caccb3bf3727c2921d74f06c1Chris Banes
1834e411251159c965caccb3bf3727c2921d74f06c1Chris Banes    /**
184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by menu to notify of close and selection changes.
18589208232f3b5d1451408d787872504a190bc7ee0Chris Banes     * @hide
186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public interface Callback {
18820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        /**
190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * Called when a menu item is selected.
19120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *
192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param menu The menu that is the parent of the item
193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param item The menu item that is selected
194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @return whether the menu item selection was handled
195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         */
196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        /**
199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * Called when the mode of the menu changes (for example, from icon to expanded).
200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         *
201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param menu the menu that has changed modes
202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         */
203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public void onMenuModeChange(MenuBuilder menu);
204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by menu items to execute their associated action
20889208232f3b5d1451408d787872504a190bc7ee0Chris Banes     * @hide
209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public interface ItemInvoker {
211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public boolean invokeItem(MenuItemImpl item);
212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder(Context context) {
215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mContext = context;
216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mResources = context.getResources();
217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems = new ArrayList<MenuItemImpl>();
219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems = new ArrayList<MenuItemImpl>();
221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mActionItems = new ArrayList<MenuItemImpl>();
224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mNonActionItems = new ArrayList<MenuItemImpl>();
225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(true);
228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mDefaultShowAsAction = defaultShowAsAction;
232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
23620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Add a presenter to this menu. This will only hold a WeakReference; you do not need to
23720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * explicitly remove a presenter, but you can using {@link #removeMenuPresenter(MenuPresenter)}.
238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to add
240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void addMenuPresenter(MenuPresenter presenter) {
24249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        addMenuPresenter(presenter, mContext);
24349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
24449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
24549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
24649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Add a presenter to this menu that uses an alternate context for
24749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * inflating menu items. This will only hold a WeakReference; you do not
24849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * need to explicitly remove a presenter, but you can using
24949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * {@link #removeMenuPresenter(MenuPresenter)}.
25049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
25149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param presenter The presenter to add
25249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param menuContext The context used to inflate menu items
25349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
25449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void addMenuPresenter(MenuPresenter presenter, Context menuContext) {
255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPresenters.add(new WeakReference<MenuPresenter>(presenter));
25649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        presenter.initForMenu(menuContext, this);
257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
26120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Remove a presenter from this menu. That presenter will no longer receive notifications of
26220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * updates to this menu's data.
263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to remove
265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeMenuPresenter(MenuPresenter presenter) {
267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter item = ref.get();
269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item == null || item == presenter) {
270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchPresenterUpdate(boolean cleared) {
27649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return;
277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.updateMenuView(cleared);
285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
29049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu,
29149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            MenuPresenter preferredPresenter) {
29249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return false;
293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean result = false;
295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
29649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // Try the preferred presenter first.
29749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (preferredPresenter != null) {
29849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            result = preferredPresenter.onSubMenuSelected(subMenu);
29949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
30049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (!result) {
306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                result = presenter.onSubMenuSelected(subMenu);
307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return result;
310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchSaveInstanceState(Bundle outState) {
31349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return;
314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    final Parcelable state = presenter.onSaveInstanceState();
325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (state != null) {
326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenterStates.put(id, state);
327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchRestoreInstanceState(Bundle state) {
336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
33849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (presenterStates == null || mPresenters.isEmpty()) return;
339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    Parcelable parcel = presenterStates.get(id);
348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (parcel != null) {
349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenter.onRestoreInstanceState(parcel);
350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void savePresenterStates(Bundle outState) {
357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchSaveInstanceState(outState);
358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restorePresenterStates(Bundle state) {
361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchRestoreInstanceState(state);
362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void saveActionViewStates(Bundle outStates) {
365ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = null;
366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
367ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
368ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
369ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
37030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
371ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
372ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (viewStates == null) {
373ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    viewStates = new SparseArray<Parcelable>();
374ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
375ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.saveHierarchyState(viewStates);
37630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                if (MenuItemCompat.isActionViewExpanded(item)) {
377ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId());
378ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
379ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
380ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
381ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
382ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.saveActionViewStates(outStates);
383ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
384ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
385ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
386ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (viewStates != null) {
387ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates);
388ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
389ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
390ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
391ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restoreActionViewStates(Bundle states) {
392ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (states == null) {
393ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
394ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
395ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
396ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = states.getSparseParcelableArray(
397ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                getActionViewStatesKey());
398ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
399ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
400ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
401ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
40230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
403ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
404ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.restoreHierarchyState(viewStates);
405ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
406ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
407ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
408ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.restoreActionViewStates(states);
409ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
410ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
411ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
412ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID);
413ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expandedId > 0) {
414ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItem itemToExpand = findItem(expandedId);
415ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (itemToExpand != null) {
41630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                MenuItemCompat.expandActionView(itemToExpand);
417ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
418ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
419ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
420ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
421ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected String getActionViewStatesKey() {
422ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return ACTION_VIEW_STATES_KEY;
423ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
424ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
425ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCallback(Callback cb) {
426ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCallback = cb;
427ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
428ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
429ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
430ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Adds an item to the menu.  The other add methods funnel to this.
431ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
4326c72ea0134a3309ff8197f0862aad8d7bc712b55Yuichi Araki    protected MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
433ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int ordering = getOrdering(categoryOrder);
434ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
43549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final MenuItemImpl item = createNewMenuItem(group, id, categoryOrder, ordering, title,
43649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                mDefaultShowAsAction);
437ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
438ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCurrentMenuInfo != null) {
439ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Pass along the current menu info
440ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item.setMenuInfo(mCurrentMenuInfo);
441ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
442ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
443ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.add(findInsertIndex(mItems, ordering), item);
444ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
445ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
446ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return item;
447ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
448ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
44949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    // Layoutlib overrides this method to return its custom implementation of MenuItemImpl
45049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private MenuItemImpl createNewMenuItem(int group, int id, int categoryOrder, int ordering,
45149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            CharSequence title, int defaultShowAsAction) {
45249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return new MenuItemImpl(this, group, id, categoryOrder, ordering, title,
45349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                defaultShowAsAction);
45449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
45549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
456ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(CharSequence title) {
457ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, title);
458ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
459ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4606e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
461ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int titleRes) {
462ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, mResources.getString(titleRes));
463ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
464ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4656e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
466ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
467ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, title);
468ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
469ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4706e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
471ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, int title) {
472ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, mResources.getString(title));
473ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
474ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4756e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
476ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(CharSequence title) {
477ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, title);
478ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
479ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4806e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
481ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int titleRes) {
482ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
483ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
484ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4856e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
486ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
487ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
488ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
489ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        item.setSubMenu(subMenu);
490ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
491ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return subMenu;
492ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
493ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4946e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
495ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
496ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
497ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
498ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4996e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
500ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
50120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
502ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        PackageManager pm = mContext.getPackageManager();
503ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final List<ResolveInfo> lri =
504ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
505ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = lri != null ? lri.size() : 0;
506ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
507ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
508ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            removeGroup(group);
509ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
510ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
51120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        for (int i = 0; i < N; i++) {
512ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final ResolveInfo ri = lri.get(i);
513ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            Intent rintent = new Intent(
514ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
515ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            rintent.setComponent(new ComponentName(
516ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.applicationInfo.packageName,
517ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.name));
518ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
519ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIcon(ri.loadIcon(pm))
520ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIntent(rintent);
521ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (outSpecificItems != null && ri.specificIndex >= 0) {
522ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                outSpecificItems[ri.specificIndex] = item;
523ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
524ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
525ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
526ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return N;
527ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
528ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5296e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
530ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItem(int id) {
531ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(findItemIndex(id), true);
532ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
533ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5346e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
535ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeGroup(int group) {
536ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int i = findGroupIndex(group);
537ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
538ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (i >= 0) {
539ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int maxRemovable = mItems.size() - i;
540ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            int numRemoved = 0;
541ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
542ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Don't force update for each one, this method will do it at the end
543ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                removeItemAtInt(i, false);
544ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
545ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
546ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Notify menu views
547ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
548ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
549ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
550ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
551ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
55249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Remove the item at the given index and optionally forces menu views to
55349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * update.
554ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
55549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param index The index of the item to be removed. If this index is
55649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            invalid an exception is thrown.
55749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param updateChildrenOnMenuViews Whether to force update on menu views.
55849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            Please make sure you eventually call this after your batch of
55949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            removals.
560ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
561ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
56249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if ((index < 0) || (index >= mItems.size())) return;
563ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
564ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.remove(index);
565ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
56649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (updateChildrenOnMenuViews) onItemsChanged(true);
567ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
568ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
569ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItemAt(int index) {
570ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(index, true);
571ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
572ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
573ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearAll() {
574ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = true;
575ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clear();
576ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clearHeader();
577ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
578ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItemsChangedWhileDispatchPrevented = false;
579ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
580ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
581ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5826e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
583ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clear() {
584ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mExpandedItem != null) {
585ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            collapseItemActionView(mExpandedItem);
586ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
587ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.clear();
588ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
589ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
590ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
591ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
592ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setExclusiveItemChecked(MenuItem item) {
593ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int group = item.getGroupId();
594ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
595ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
596ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
597ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl curItem = mItems.get(i);
598ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (curItem.getGroupId() == group) {
59949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (!curItem.isExclusiveCheckable()) continue;
60049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (!curItem.isCheckable()) continue;
601ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
602ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Check the item meant to be checked, uncheck the others (that are in the group)
603ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                curItem.setCheckedInt(curItem == item);
604ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
605ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
606ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
607ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6086e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
609ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
610ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
611ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
612ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
613ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
614ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
615ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setExclusiveCheckable(exclusive);
616ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setCheckable(checkable);
617ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
618ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
619ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
620ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6216e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
622ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupVisible(int group, boolean visible) {
623ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
624ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
62549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
62649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // than setVisible and at the end notify of items being changed
627ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
628ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean changedAtLeastOneItem = false;
629ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
630ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
631ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
63249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
633ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
634ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
635ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
63649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (changedAtLeastOneItem) onItemsChanged(true);
637ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
638ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6396e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
640ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupEnabled(int group, boolean enabled) {
641ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
642ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
643ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
644ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
645ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
646ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setEnabled(enabled);
647ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
648ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
649ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
650ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6516e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
652ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean hasVisibleItems() {
6534e411251159c965caccb3bf3727c2921d74f06c1Chris Banes        if (mOverrideVisibleItems) {
6544e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            return true;
6554e411251159c965caccb3bf3727c2921d74f06c1Chris Banes        }
6564e411251159c965caccb3bf3727c2921d74f06c1Chris Banes
657ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
658bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
659ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
660ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
661ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.isVisible()) {
662ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return true;
663ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
664ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
665bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
666ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
667ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
668bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
6696e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
670ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem findItem(int id) {
671ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
672ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
673ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
674ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
675ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
676ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (item.hasSubMenu()) {
677ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItem possibleItem = item.getSubMenu().findItem(id);
678bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
679ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (possibleItem != null) {
680ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    return possibleItem;
681ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
682ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
683ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
684bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
685ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
686ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
687bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
688ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findItemIndex(int id) {
689ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
690bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
691ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
692ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
693ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
694ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
695ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
696ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
697bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
698ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
699ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
700bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
701ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group) {
702ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findGroupIndex(group, 0);
703ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
704bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
705ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group, int start) {
706ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
707bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
708ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (start < 0) {
709ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            start = 0;
710ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
711ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
712ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = start; i < size; i++) {
713ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = mItems.get(i);
714ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
715ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
716ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
717ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
718ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
719ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
720ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
721ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
722ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7236e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
724ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int size() {
725ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.size();
726ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
727ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7286e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
729ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem getItem(int index) {
730ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.get(index);
731ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
732ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7336e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
734ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutKey(int keyCode, KeyEvent event) {
735ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findItemWithShortcutForKey(keyCode, event) != null;
736ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
737ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7386e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
739ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setQwertyMode(boolean isQwerty) {
740ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mQwertyMode = isQwerty;
741ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
742ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
743ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
744ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
745ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
74649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Returns the ordering across all items. This will grab the category from
74749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the upper bits, find out how to order the category with respect to other
74849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * categories, and combine it with the lower bits.
749ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
75049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param categoryOrder The category order for a particular item (if it has
75149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            not been or/add with a category, the default category is
75249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            assumed).
75349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return An ordering integer that can be used to order this item across
75449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *         all the items (even from other categories).
755ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
756ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int getOrdering(int categoryOrder) {
757ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
758ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
759ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (index < 0 || index >= sCategoryToOrder.length) {
760ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            throw new IllegalArgumentException("order does not contain a valid category.");
761ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
762ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
763ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
764ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
765b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
766b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
767ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return whether the menu shortcuts are in qwerty mode or not
768b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
769ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean isQwertyMode() {
770ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mQwertyMode;
771ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
772b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
773b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
77420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets whether the shortcuts should be visible on menus.  Devices without hardware key input
77520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * will never make shortcuts visible even if this method is passed 'true'.
776b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     *
77720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param shortcutsVisible Whether shortcuts should be visible (if true and a menu item does not
77820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         have a shortcut defined, that item will still NOT show a shortcut)
779ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
780ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setShortcutsVisible(boolean shortcutsVisible) {
78120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mShortcutsVisible == shortcutsVisible) {
78220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
78320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
784ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
785ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(shortcutsVisible);
786ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
787ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
788ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
789ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setShortcutsVisibleInner(boolean shortcutsVisible) {
790ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mShortcutsVisible = shortcutsVisible
791ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS
79207a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes                && mResources.getBoolean(R.bool.abc_config_showMenuShortcutsWhenKeyboardPresent);
793ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
794ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
795ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
796ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return Whether shortcuts should be visible on menus.
797ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
798ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutsVisible() {
799ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mShortcutsVisible;
800ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
801ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
802ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Resources getResources() {
803ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mResources;
804ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
805ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
806ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Context getContext() {
807ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mContext;
808ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
809ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
810ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) {
811ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mCallback != null && mCallback.onMenuItemSelected(menu, item);
812ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
813ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
814ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
815ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Dispatch a mode change event to this menu's callback.
816ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
817ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void changeMenuMode() {
818ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCallback != null) {
819ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mCallback.onMenuModeChange(this);
820ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
821ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
822ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
823ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
824ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = items.size() - 1; i >= 0; i--) {
825ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = items.get(i);
826ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getOrdering() <= ordering) {
827ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i + 1;
828ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
829ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
830ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
831ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return 0;
832ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
833ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
8346e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
835ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
836ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
837ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
838ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean handled = false;
839ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
840ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (item != null) {
841ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            handled = performItemAction(item, flags);
842ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
843ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
844ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
845ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            close(true);
846ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
847ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
848ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return handled;
849ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
850ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
851ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
852ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This function will return all the menu and sub-menu items that can
853ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * be directly (the shortcut directly corresponds) and indirectly
854ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * (the ALT-enabled char corresponds to the shortcut) associated
855ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * with the keyCode.
856ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8576e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
858ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
859ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
860ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
861ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
862ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
863ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
864ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // The delete key is not mapped to '\b' so we treat it specially
865ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
866ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
867ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
868ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
869ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose shortcut is this key.
870ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
871ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
872ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
873ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
87449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                ((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
875ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
87649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
877ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
87849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  (shortcutChar != 0) &&
87949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  (shortcutChar == possibleChars.meta[0]
88049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                      || shortcutChar == possibleChars.meta[2]
88149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                      || (qwerty && shortcutChar == '\b' &&
88249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                          keyCode == KeyEvent.KEYCODE_DEL)) &&
88349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  item.isEnabled()) {
884ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                items.add(item);
885ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
886ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
887ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
888ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
889ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
890ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * We want to return the menu item associated with the key, but if there is no
891ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * ambiguity (i.e. there is only one menu item corresponding to the key) we want
892ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to return it even if it's not an exact match; this allow the user to
893ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * _not_ use the ALT key for example, making the use of shortcuts slightly more
894ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
895ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
896ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
897ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * On the other hand, if two (or more) shortcuts corresponds to the same key,
898ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * we have to only return the exact match.
899ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
9006e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
901ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
902ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get all items that can be associated directly or indirectly with the keyCode
903ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        ArrayList<MenuItemImpl> items = mTempShortcutItemList;
904ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        items.clear();
905ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        findItemsWithShortcutForKey(items, keyCode, event);
906ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
907ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (items.isEmpty()) {
908ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return null;
909ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
910ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
911ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
912ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
913ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
914ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        event.getKeyData(possibleChars);
915ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
916ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we have only one element, we can safely returns it
917ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = items.size();
918ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (size == 1) {
919ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.get(0);
920ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
921ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
922ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
923ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we found more than one item associated with the key,
924ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // we have to return the exact match
925ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
926ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = items.get(i);
927ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
928ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    item.getNumericShortcut();
929ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((shortcutChar == possibleChars.meta[0] &&
930ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) == 0)
93149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                || (shortcutChar == possibleChars.meta[2] &&
932ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) != 0)
93349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                || (qwerty && shortcutChar == '\b' &&
934ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    keyCode == KeyEvent.KEYCODE_DEL)) {
935ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
936ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
937ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
938ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
939ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
940ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9416e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
942ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performIdentifierAction(int id, int flags) {
943ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose identifier is the id.
944ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return performItemAction(findItem(id), flags);
945ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
946ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
947ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performItemAction(MenuItem item, int flags) {
94849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return performItemAction(item, null, flags);
94949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
95049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
95149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public boolean performItemAction(MenuItem item, MenuPresenter preferredPresenter, int flags) {
952ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl itemImpl = (MenuItemImpl) item;
953ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
954ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl == null || !itemImpl.isEnabled()) {
955ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return false;
956ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
957ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
958ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean invoked = itemImpl.invoke();
959ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
96030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        final ActionProvider provider = itemImpl.getSupportActionProvider();
961ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean providerHasSubMenu = provider != null && provider.hasSubMenu();
962ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl.hasCollapsibleActionView()) {
963ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            invoked |= itemImpl.expandActionView();
96449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (invoked) close(true);
965ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else if (itemImpl.hasSubMenu() || providerHasSubMenu) {
966ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            close(false);
967ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
968ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (!itemImpl.hasSubMenu()) {
969ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemImpl.setSubMenu(new SubMenuBuilder(getContext(), this, itemImpl));
970ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
971ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
972ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final SubMenuBuilder subMenu = (SubMenuBuilder) itemImpl.getSubMenu();
973ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (providerHasSubMenu) {
974ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                provider.onPrepareSubMenu(subMenu);
975ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
97649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            invoked |= dispatchSubMenuSelected(subMenu, preferredPresenter);
97749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (!invoked) close(true);
978ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
979ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
980ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                close(true);
981ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
982ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
983ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
984ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return invoked;
985ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
986ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
987ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
988ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Closes the visible menu.
989ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
99049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param allMenusAreClosing Whether the menus are completely closing (true),
99149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            or whether there is another menu coming in this menu's place
99249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            (false). For example, if the menu is closing because a
99349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            sub menu is about to be shown, <var>allMenusAreClosing</var>
99449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            is false.
995ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
99649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public final void close(boolean allMenusAreClosing) {
99749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mIsClosing) return;
998ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
999ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = true;
1000ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1001ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1002ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1003ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1004ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
1005ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.onCloseMenu(this, allMenusAreClosing);
1006ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1007ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1008ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = false;
1009ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1010ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
10116e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
1012ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void close() {
1013ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        close(true);
1014ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1015ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1016ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1017ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called when an item is added or removed.
1018ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
101949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param structureChanged true if the menu structure changed,
102049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *                         false if only item properties changed.
102149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *                         (Visibility is a structural property since it affects layout.)
1022ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
102349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void onItemsChanged(boolean structureChanged) {
1024ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mPreventDispatchingItemsChanged) {
1025ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (structureChanged) {
1026ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mIsVisibleItemsStale = true;
1027ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mIsActionItemsStale = true;
1028ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1029ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1030ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            dispatchPresenterUpdate(structureChanged);
1031ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1032ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = true;
1033ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1034ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1035ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1036ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
103749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Stop dispatching item changed events to presenters until
103849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * {@link #startDispatchingItemsChanged()} is called. Useful when
103949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * many menu operations are going to be performed as a batch.
1040ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1041ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void stopDispatchingItemsChanged() {
1042ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mPreventDispatchingItemsChanged) {
1043ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPreventDispatchingItemsChanged = true;
1044ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = false;
1045ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1046ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1047ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1048ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void startDispatchingItemsChanged() {
1049ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
1050ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1051ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mItemsChangedWhileDispatchPrevented) {
1052ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = false;
1053ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
1054ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1055ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1056ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1057ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1058ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by {@link MenuItemImpl} when its visible flag is changed.
105920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1060ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param item The item that has gone through a visibility change.
1061b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
1062ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemVisibleChanged(MenuItemImpl item) {
1063ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of items being changed
1064ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
1065ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
1066ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1067ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1068ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1069ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by {@link MenuItemImpl} when its action request status is changed.
107020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1071ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param item The item that has gone through a change in action request status.
1072ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1073ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemActionRequestChanged(MenuItemImpl item) {
1074ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of items being changed
1075ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1076ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
1077ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1078ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
107949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getVisibleItems() {
108049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (!mIsVisibleItemsStale) return mVisibleItems;
1081ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1082ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Refresh the visible items
1083ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems.clear();
1084ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1085ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemsSize = mItems.size();
1086ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl item;
1087ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemsSize; i++) {
1088ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item = mItems.get(i);
108949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (item.isVisible()) mVisibleItems.add(item);
1090ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1091ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1092ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = false;
1093ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1094ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1095ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mVisibleItems;
1096ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1097ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1098ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1099ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This method determines which menu items get to be 'action items' that will appear
1100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in an action bar and which items should be 'overflow items' in a secondary menu.
1101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * The rules are as follows:
1102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>Items are considered for inclusion in the order specified within the menu.
1104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * There is a limit of mMaxActionItems as a total count, optionally including the overflow
1105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * menu button itself. This is a soft limit; if an item shares a group ID with an item
1106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * previously included as an action item, the new item will stay with its group and become
1107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * an action item itself even if it breaks the max item count limit. This is done to
1108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit the conceptual complexity of the items presented within an action bar. Only a few
1109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * unrelated concepts should be presented to the user in this space, and groups are treated
1110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * as a single concept.
1111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This
1113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit may be broken by a single item that exceeds the remaining space, but no further
1114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * items may be added. If an item that is part of a group cannot fit within the remaining
1115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * measured width, the entire group will be demoted to overflow. This is done to ensure room
1116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * for navigation and other affordances in the action bar as well as reduce general UI clutter.
1117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>The space freed by demoting a full group cannot be consumed by future menu items.
1119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Once items begin to overflow, all future items become overflow items as well. This is
1120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to avoid inadvertent reordering that may break the app's intended design.
1121ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1122ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void flagActionItems() {
112349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // Important side effect: if getVisibleItems is stale it may refresh,
112449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // which can affect action items staleness.
112549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
112649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
1127ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mIsActionItemsStale) {
1128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
1129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Presenters flag action items as needed.
1132ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean flagged = false;
1133ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
1138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                flagged |= presenter.flagActionItems();
1139ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (flagged) {
1143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int itemsSize = visibleItems.size();
1146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            for (int i = 0; i < itemsSize; i++) {
1147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItemImpl item = visibleItems.get(i);
1148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (item.isActionButton()) {
1149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mActionItems.add(item);
1150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                } else {
1151ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mNonActionItems.add(item);
1152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
1153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Nobody flagged anything, everything is a non-action item.
1156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // (This happens during a first pass with no action-item presenters.)
1157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.addAll(getVisibleItems());
1160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = false;
1162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
116449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getActionItems() {
1165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mActionItems;
1167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
116949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getNonActionItems() {
1170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mNonActionItems;
1172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearHeader() {
1175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderIcon = null;
1176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderTitle = null;
1177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderView = null;
1178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
118320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final Drawable icon, final View view) {
1184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Resources r = getResources();
1185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (view != null) {
1187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = view;
1188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using a custom view, then the title and icon aren't used
1190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderTitle = null;
1191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderIcon = null;
1192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (titleRes > 0) {
1194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = r.getText(titleRes);
1195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (title != null) {
1196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = title;
1197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (iconRes > 0) {
12007fa6a00a4600aac591402398c23fea97721adf26Chris Banes                mHeaderIcon = ContextCompat.getDrawable(getContext(), iconRes);
1201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (icon != null) {
1202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderIcon = icon;
1203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using the title or icon, then a custom view isn't used
1206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = null;
1207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of change
1210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
121449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's title. This replaces the header view. Called by the
121549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param title The new title.
1218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
1221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, title, 0, null, null);
1222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
122649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's title. This replaces the header view. Called by the
122749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param titleRes The new title (as a resource ID).
1230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(int titleRes) {
1233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(titleRes, null, 0, null, null);
1234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
123849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's icon. This replaces the header view. Called by the
123949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param icon The new icon.
1242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(Drawable icon) {
1245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, icon, null);
1246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
125049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's icon. This replaces the header view. Called by the
125149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param iconRes The new icon (as a resource ID).
1254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(int iconRes) {
1257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, iconRes, null, null);
1258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
126249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's view. This replaces the title and icon. Called by the
126349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param view The new view.
1266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderViewInt(View view) {
1269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, null, view);
1270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public CharSequence getHeaderTitle() {
1274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderTitle;
1275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Drawable getHeaderIcon() {
1278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderIcon;
1279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public View getHeaderView() {
1282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderView;
1283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Gets the root menu (if this is a submenu, find its root menu).
128720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return The root menu.
1289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder getRootMenu() {
1291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
129549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the current menu info that is set on all items added to this menu
129649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * (until this is called again with different menu info, in which case that
129749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * one will be added to all subsequent item additions).
1298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param menuInfo The extra menu information to add.
1300ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCurrentMenuInfo(ContextMenu.ContextMenuInfo menuInfo) {
1302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCurrentMenuInfo = menuInfo;
1303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setOptionalIconsVisible(boolean visible) {
1306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mOptionalIconsVisible = visible;
1307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean getOptionalIconsVisible() {
1310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mOptionalIconsVisible;
1311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean expandItemActionView(MenuItemImpl item) {
131449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return false;
1315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean expanded = false;
1317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
1319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if ((expanded = presenter.expandItemActionView(this, item))) {
1324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                break;
1325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
1328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expanded) {
1330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedItem = item;
1331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return expanded;
1333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean collapseItemActionView(MenuItemImpl item) {
133649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty() || mExpandedItem != item) return false;
1337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean collapsed = false;
1339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
1341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if ((collapsed = presenter.collapseItemActionView(this, item))) {
1346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                break;
1347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
1350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (collapsed) {
1352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedItem = null;
1353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return collapsed;
1355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItemImpl getExpandedItem() {
1358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mExpandedItem;
1359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
13604e411251159c965caccb3bf3727c2921d74f06c1Chris Banes
13614e411251159c965caccb3bf3727c2921d74f06c1Chris Banes    /**
13624e411251159c965caccb3bf3727c2921d74f06c1Chris Banes     * Allows us to override the value of {@link #hasVisibleItems()} and make it always return true.
13634e411251159c965caccb3bf3727c2921d74f06c1Chris Banes     *
13644e411251159c965caccb3bf3727c2921d74f06c1Chris Banes     * @param override
13654e411251159c965caccb3bf3727c2921d74f06c1Chris Banes     */
13664e411251159c965caccb3bf3727c2921d74f06c1Chris Banes    public void setOverrideVisibleItems(boolean override) {
13674e411251159c965caccb3bf3727c2921d74f06c1Chris Banes        mOverrideVisibleItems = override;
13684e411251159c965caccb3bf3727c2921d74f06c1Chris Banes    }
1369bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell}
1370ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1371