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
1766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banespackage android.support.v7.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;
296142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.NonNull;
307fa6a00a4600aac591402398c23fea97721adf26Chris Banesimport android.support.v4.content.ContextCompat;
3130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenu;
3230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenuItem;
3366698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v4.view.ActionProvider;
3466698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v4.view.MenuItemCompat;
3566698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesimport android.support.v7.appcompat.R;
36ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.util.SparseArray;
37ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.view.ContextMenu;
38ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.view.KeyCharacterMap;
39bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.KeyEvent;
4030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
4130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.SubMenu;
42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View;
43bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
44ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.lang.ref.WeakReference;
45bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList;
46ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.util.List;
47ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.util.concurrent.CopyOnWriteArrayList;
48bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
49bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/**
5030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell * Implementation of the {@link android.support.v4.internal.view.SupportMenu} interface for creating a
51ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani * standard menu UI.
5289208232f3b5d1451408d787872504a190bc7ee0Chris Banes *
5389208232f3b5d1451408d787872504a190bc7ee0Chris Banes * @hide
54bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
5530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellpublic class MenuBuilder implements SupportMenu {
5620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
57ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String TAG = "MenuBuilder";
58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
59ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String PRESENTER_KEY = "android:menu:presenters";
60ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview";
62ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private static final int[] sCategoryToOrder = new int[]{
64ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            1, /* No category */
65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            4, /* CONTAINER */
66ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            5, /* SYSTEM */
67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            3, /* SECONDARY */
68ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            2, /* ALTERNATIVE */
69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            0, /* SELECTED_ALTERNATIVE */
70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    };
71ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
72ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Context mContext;
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();
2176142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        mItems = new ArrayList<>();
218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
2196142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        mVisibleItems = new ArrayList<>();
220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
2226142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        mActionItems = new ArrayList<>();
2236142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        mNonActionItems = new ArrayList<>();
224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(true);
227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mDefaultShowAsAction = defaultShowAsAction;
231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
23520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Add a presenter to this menu. This will only hold a WeakReference; you do not need to
23620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * explicitly remove a presenter, but you can using {@link #removeMenuPresenter(MenuPresenter)}.
237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to add
239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void addMenuPresenter(MenuPresenter presenter) {
24149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        addMenuPresenter(presenter, mContext);
24249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
24349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
24449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
24549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Add a presenter to this menu that uses an alternate context for
24649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * inflating menu items. This will only hold a WeakReference; you do not
24749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * need to explicitly remove a presenter, but you can using
24849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * {@link #removeMenuPresenter(MenuPresenter)}.
24949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
25049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param presenter The presenter to add
25149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param menuContext The context used to inflate menu items
25249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
25349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void addMenuPresenter(MenuPresenter presenter, Context menuContext) {
254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPresenters.add(new WeakReference<MenuPresenter>(presenter));
25549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        presenter.initForMenu(menuContext, this);
256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
26020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Remove a presenter from this menu. That presenter will no longer receive notifications of
26120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * updates to this menu's data.
262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to remove
264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeMenuPresenter(MenuPresenter presenter) {
266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter item = ref.get();
268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item == null || item == presenter) {
269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchPresenterUpdate(boolean cleared) {
27549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return;
276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.updateMenuView(cleared);
284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
28949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu,
29049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            MenuPresenter preferredPresenter) {
29149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return false;
292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean result = false;
294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
29549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // Try the preferred presenter first.
29649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (preferredPresenter != null) {
29749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            result = preferredPresenter.onSubMenuSelected(subMenu);
29849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
29949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
300ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (!result) {
305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                result = presenter.onSubMenuSelected(subMenu);
306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return result;
309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchSaveInstanceState(Bundle outState) {
31249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return;
313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    final Parcelable state = presenter.onSaveInstanceState();
324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (state != null) {
325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenterStates.put(id, state);
326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchRestoreInstanceState(Bundle state) {
335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
33749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (presenterStates == null || mPresenters.isEmpty()) return;
338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    Parcelable parcel = presenterStates.get(id);
347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (parcel != null) {
348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenter.onRestoreInstanceState(parcel);
349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void savePresenterStates(Bundle outState) {
356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchSaveInstanceState(outState);
357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restorePresenterStates(Bundle state) {
360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchRestoreInstanceState(state);
361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void saveActionViewStates(Bundle outStates) {
364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = null;
365ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
367ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
368ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
36930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
370ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
371ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (viewStates == null) {
372ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    viewStates = new SparseArray<Parcelable>();
373ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
374ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.saveHierarchyState(viewStates);
37530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                if (MenuItemCompat.isActionViewExpanded(item)) {
376ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId());
377ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
378ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
379ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
380ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
381ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.saveActionViewStates(outStates);
382ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
383ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
384ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
385ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (viewStates != null) {
386ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates);
387ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
388ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
389ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
390ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restoreActionViewStates(Bundle states) {
391ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (states == null) {
392ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
393ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
394ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
395ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = states.getSparseParcelableArray(
396ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                getActionViewStatesKey());
397ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
398ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
399ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
400ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
40130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
402ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
403ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.restoreHierarchyState(viewStates);
404ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
405ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
406ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
407ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.restoreActionViewStates(states);
408ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
409ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
410ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
411ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID);
412ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expandedId > 0) {
413ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItem itemToExpand = findItem(expandedId);
414ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (itemToExpand != null) {
41530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                MenuItemCompat.expandActionView(itemToExpand);
416ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
417ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
418ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
419ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
420ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected String getActionViewStatesKey() {
421ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return ACTION_VIEW_STATES_KEY;
422ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
423ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
424ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCallback(Callback cb) {
425ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCallback = cb;
426ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
427ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
428ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
429ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Adds an item to the menu.  The other add methods funnel to this.
430ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
4316c72ea0134a3309ff8197f0862aad8d7bc712b55Yuichi Araki    protected MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
432ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int ordering = getOrdering(categoryOrder);
433ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
43449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final MenuItemImpl item = createNewMenuItem(group, id, categoryOrder, ordering, title,
43549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                mDefaultShowAsAction);
436ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
437ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCurrentMenuInfo != null) {
438ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Pass along the current menu info
439ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item.setMenuInfo(mCurrentMenuInfo);
440ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
441ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
442ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.add(findInsertIndex(mItems, ordering), item);
443ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
444ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
445ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return item;
446ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
447ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
44849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    // Layoutlib overrides this method to return its custom implementation of MenuItemImpl
44949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private MenuItemImpl createNewMenuItem(int group, int id, int categoryOrder, int ordering,
45049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            CharSequence title, int defaultShowAsAction) {
45149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return new MenuItemImpl(this, group, id, categoryOrder, ordering, title,
45249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                defaultShowAsAction);
45349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
45449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
455ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(CharSequence title) {
456ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, title);
457ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
458ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4596e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
460ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int titleRes) {
461ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, mResources.getString(titleRes));
462ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
463ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4646e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
465ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
466ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, title);
467ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
468ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4696e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
470ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, int title) {
471ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, mResources.getString(title));
472ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
473ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4746e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
475ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(CharSequence title) {
476ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, title);
477ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
478ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4796e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
480ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int titleRes) {
481ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
482ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
483ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4846e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
485ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
486ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
487ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
488ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        item.setSubMenu(subMenu);
489ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
490ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return subMenu;
491ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
492ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4936e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
494ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
495ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
496ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
497ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4986e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
499ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
50020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
501ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        PackageManager pm = mContext.getPackageManager();
502ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final List<ResolveInfo> lri =
503ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
504ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = lri != null ? lri.size() : 0;
505ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
506ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
507ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            removeGroup(group);
508ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
509ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
51020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        for (int i = 0; i < N; i++) {
511ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final ResolveInfo ri = lri.get(i);
512ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            Intent rintent = new Intent(
513ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
514ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            rintent.setComponent(new ComponentName(
515ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.applicationInfo.packageName,
516ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.name));
517ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
518ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIcon(ri.loadIcon(pm))
519ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIntent(rintent);
520ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (outSpecificItems != null && ri.specificIndex >= 0) {
521ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                outSpecificItems[ri.specificIndex] = item;
522ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
523ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
524ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
525ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return N;
526ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
527ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5286e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
529ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItem(int id) {
530ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(findItemIndex(id), true);
531ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
532ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5336e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
534ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeGroup(int group) {
535ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int i = findGroupIndex(group);
536ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
537ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (i >= 0) {
538ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int maxRemovable = mItems.size() - i;
539ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            int numRemoved = 0;
540ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
541ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Don't force update for each one, this method will do it at the end
542ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                removeItemAtInt(i, false);
543ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
544ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
545ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Notify menu views
546ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
547ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
548ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
549ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
550ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
55149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Remove the item at the given index and optionally forces menu views to
55249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * update.
553ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
55449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param index The index of the item to be removed. If this index is
55549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            invalid an exception is thrown.
55649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param updateChildrenOnMenuViews Whether to force update on menu views.
55749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            Please make sure you eventually call this after your batch of
55849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            removals.
559ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
560ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
56149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if ((index < 0) || (index >= mItems.size())) return;
562ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
563ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.remove(index);
564ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
56549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (updateChildrenOnMenuViews) onItemsChanged(true);
566ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
567ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
568ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItemAt(int index) {
569ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(index, true);
570ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
571ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
572ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearAll() {
573ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = true;
574ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clear();
575ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clearHeader();
576ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
577ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItemsChangedWhileDispatchPrevented = false;
578ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
579ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
580ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5816e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
582ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clear() {
583ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mExpandedItem != null) {
584ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            collapseItemActionView(mExpandedItem);
585ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
586ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.clear();
587ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
588ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
589ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
590ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
591ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setExclusiveItemChecked(MenuItem item) {
592ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int group = item.getGroupId();
593ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
594ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
595ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
596ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl curItem = mItems.get(i);
597ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (curItem.getGroupId() == group) {
59849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (!curItem.isExclusiveCheckable()) continue;
59949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (!curItem.isCheckable()) continue;
600ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
601ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Check the item meant to be checked, uncheck the others (that are in the group)
602ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                curItem.setCheckedInt(curItem == item);
603ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
604ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
605ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
606ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6076e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
608ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
609ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
610ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
611ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
612ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
613ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
614ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setExclusiveCheckable(exclusive);
615ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setCheckable(checkable);
616ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
617ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
618ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
619ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6206e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
621ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupVisible(int group, boolean visible) {
622ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
623ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
62449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
62549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // than setVisible and at the end notify of items being changed
626ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
627ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean changedAtLeastOneItem = false;
628ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
629ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
630ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
63149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
632ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
633ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
634ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
63549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (changedAtLeastOneItem) onItemsChanged(true);
636ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
637ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6386e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
639ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupEnabled(int group, boolean enabled) {
640ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
641ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
642ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
643ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
644ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
645ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setEnabled(enabled);
646ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
647ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
648ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
649ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6506e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
651ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean hasVisibleItems() {
6524e411251159c965caccb3bf3727c2921d74f06c1Chris Banes        if (mOverrideVisibleItems) {
6534e411251159c965caccb3bf3727c2921d74f06c1Chris Banes            return true;
6544e411251159c965caccb3bf3727c2921d74f06c1Chris Banes        }
6554e411251159c965caccb3bf3727c2921d74f06c1Chris Banes
656ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
657bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
658ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
659ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
660ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.isVisible()) {
661ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return true;
662ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
663ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
664bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
665ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
666ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
667bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
6686e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
669ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem findItem(int id) {
670ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
671ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
672ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
673ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
674ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
675ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (item.hasSubMenu()) {
676ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItem possibleItem = item.getSubMenu().findItem(id);
677bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
678ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (possibleItem != null) {
679ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    return possibleItem;
680ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
681ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
682ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
683bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
684ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
685ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
686bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
687ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findItemIndex(int id) {
688ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
689bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
690ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
691ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
692ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
693ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
694ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
695ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
696bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
697ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
698ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
699bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
700ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group) {
701ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findGroupIndex(group, 0);
702ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
703bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
704ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group, int start) {
705ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
706bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
707ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (start < 0) {
708ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            start = 0;
709ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
710ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
711ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = start; i < size; i++) {
712ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = mItems.get(i);
713ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
714ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
715ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
716ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
717ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
718ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
719ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
720ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
721ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7226e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
723ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int size() {
724ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.size();
725ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
726ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7276e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
728ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem getItem(int index) {
729ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.get(index);
730ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
731ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7326e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
733ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutKey(int keyCode, KeyEvent event) {
734ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findItemWithShortcutForKey(keyCode, event) != null;
735ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
736ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7376e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
738ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setQwertyMode(boolean isQwerty) {
739ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mQwertyMode = isQwerty;
740ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
741ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
742ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
743ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
744ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
74549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Returns the ordering across all items. This will grab the category from
74649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the upper bits, find out how to order the category with respect to other
74749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * categories, and combine it with the lower bits.
748ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
74949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param categoryOrder The category order for a particular item (if it has
75049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            not been or/add with a category, the default category is
75149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            assumed).
75249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return An ordering integer that can be used to order this item across
75349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *         all the items (even from other categories).
754ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
755ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int getOrdering(int categoryOrder) {
756ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
757ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
758ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (index < 0 || index >= sCategoryToOrder.length) {
759ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            throw new IllegalArgumentException("order does not contain a valid category.");
760ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
761ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
762ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
763ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
764b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
765b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
766ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return whether the menu shortcuts are in qwerty mode or not
767b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
768ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean isQwertyMode() {
769ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mQwertyMode;
770ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
771b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
772b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
77320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets whether the shortcuts should be visible on menus.  Devices without hardware key input
77420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * will never make shortcuts visible even if this method is passed 'true'.
775b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     *
77620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param shortcutsVisible Whether shortcuts should be visible (if true and a menu item does not
77720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         have a shortcut defined, that item will still NOT show a shortcut)
778ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
779ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setShortcutsVisible(boolean shortcutsVisible) {
78020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mShortcutsVisible == shortcutsVisible) {
78120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
78220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
783ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
784ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(shortcutsVisible);
785ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
786ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
787ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
788ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setShortcutsVisibleInner(boolean shortcutsVisible) {
789ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mShortcutsVisible = shortcutsVisible
790ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS
79107a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes                && mResources.getBoolean(R.bool.abc_config_showMenuShortcutsWhenKeyboardPresent);
792ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
793ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
794ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
795ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return Whether shortcuts should be visible on menus.
796ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
797ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutsVisible() {
798ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mShortcutsVisible;
799ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
800ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
801ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Resources getResources() {
802ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mResources;
803ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
804ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
805ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Context getContext() {
806ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mContext;
807ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
808ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
809ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) {
810ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mCallback != null && mCallback.onMenuItemSelected(menu, item);
811ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
812ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
813ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
814ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Dispatch a mode change event to this menu's callback.
815ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
816ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void changeMenuMode() {
817ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCallback != null) {
818ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mCallback.onMenuModeChange(this);
819ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
820ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
821ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
822ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
823ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = items.size() - 1; i >= 0; i--) {
824ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = items.get(i);
825ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getOrdering() <= ordering) {
826ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i + 1;
827ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
828ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
829ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
830ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return 0;
831ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
832ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
8336e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
834ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
835ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
836ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
837ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean handled = false;
838ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
839ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (item != null) {
840ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            handled = performItemAction(item, flags);
841ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
842ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
843ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
8446142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            close(true /* closeAllMenus */);
845ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
846ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
847ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return handled;
848ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
849ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
850ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
851ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This function will return all the menu and sub-menu items that can
852ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * be directly (the shortcut directly corresponds) and indirectly
853ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * (the ALT-enabled char corresponds to the shortcut) associated
854ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * with the keyCode.
855ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8566e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
857ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
858ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
859ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
860ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
861ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
862ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
863ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // The delete key is not mapped to '\b' so we treat it specially
864ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
865ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
866ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
867ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
868ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose shortcut is this key.
869ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
870ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
871ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
872ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
87349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                ((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
874ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
87549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
876ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
87749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  (shortcutChar != 0) &&
87849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  (shortcutChar == possibleChars.meta[0]
87949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                      || shortcutChar == possibleChars.meta[2]
88049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                      || (qwerty && shortcutChar == '\b' &&
88149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                          keyCode == KeyEvent.KEYCODE_DEL)) &&
88249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  item.isEnabled()) {
883ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                items.add(item);
884ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
885ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
886ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
887ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
888ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
889ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * We want to return the menu item associated with the key, but if there is no
890ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * ambiguity (i.e. there is only one menu item corresponding to the key) we want
891ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to return it even if it's not an exact match; this allow the user to
892ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * _not_ use the ALT key for example, making the use of shortcuts slightly more
893ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
894ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
895ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
896ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * On the other hand, if two (or more) shortcuts corresponds to the same key,
897ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * we have to only return the exact match.
898ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8996e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
900ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
901ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get all items that can be associated directly or indirectly with the keyCode
902ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        ArrayList<MenuItemImpl> items = mTempShortcutItemList;
903ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        items.clear();
904ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        findItemsWithShortcutForKey(items, keyCode, event);
905ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
906ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (items.isEmpty()) {
907ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return null;
908ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
909ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
910ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
911ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
912ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
913ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        event.getKeyData(possibleChars);
914ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
915ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we have only one element, we can safely returns it
916ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = items.size();
917ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (size == 1) {
918ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.get(0);
919ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
920ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
921ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
922ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we found more than one item associated with the key,
923ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // we have to return the exact match
924ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
925ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = items.get(i);
926ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
927ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    item.getNumericShortcut();
928ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((shortcutChar == possibleChars.meta[0] &&
929ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) == 0)
93049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                || (shortcutChar == possibleChars.meta[2] &&
931ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) != 0)
93249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                || (qwerty && shortcutChar == '\b' &&
933ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    keyCode == KeyEvent.KEYCODE_DEL)) {
934ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
935ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
936ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
937ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
938ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
939ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9406e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
941ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performIdentifierAction(int id, int flags) {
942ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose identifier is the id.
943ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return performItemAction(findItem(id), flags);
944ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
945ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
946ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performItemAction(MenuItem item, int flags) {
94749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return performItemAction(item, null, flags);
94849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
94949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
95049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public boolean performItemAction(MenuItem item, MenuPresenter preferredPresenter, int flags) {
951ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl itemImpl = (MenuItemImpl) item;
952ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
953ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl == null || !itemImpl.isEnabled()) {
954ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return false;
955ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
956ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
957ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean invoked = itemImpl.invoke();
958ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
95930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        final ActionProvider provider = itemImpl.getSupportActionProvider();
960ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean providerHasSubMenu = provider != null && provider.hasSubMenu();
961ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl.hasCollapsibleActionView()) {
962ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            invoked |= itemImpl.expandActionView();
9636142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            if (invoked) {
9646142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                close(true /* closeAllMenus */);
9656142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            }
966ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else if (itemImpl.hasSubMenu() || providerHasSubMenu) {
967ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (!itemImpl.hasSubMenu()) {
968ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemImpl.setSubMenu(new SubMenuBuilder(getContext(), this, itemImpl));
969ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
970ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
971ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final SubMenuBuilder subMenu = (SubMenuBuilder) itemImpl.getSubMenu();
972ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (providerHasSubMenu) {
973ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                provider.onPrepareSubMenu(subMenu);
974ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
97549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            invoked |= dispatchSubMenuSelected(subMenu, preferredPresenter);
9766142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            if (!invoked) {
9776142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                close(true /* closeAllMenus */);
9786142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            }
979ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
980ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
9816142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                close(true /* closeAllMenus */);
982ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
983ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
984ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
985ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return invoked;
986ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
987ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
988ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
9896142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * Closes the menu.
990ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
9916142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * @param closeAllMenus {@code true} if all displayed menus and submenus
9926142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     *                      should be completely closed (as when a menu item is
9936142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     *                      selected) or {@code false} if only this menu should
9946142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     *                      be closed
995ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
9966142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public final void close(boolean closeAllMenus) {
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 {
10056142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                presenter.onCloseMenu(this, closeAllMenus);
1006ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1007ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1008ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = false;
1009ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1010ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
10116e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
1012ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void close() {
10136142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        close(true /* closeAllMenus */);
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
10796142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    @NonNull
108049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getVisibleItems() {
108149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (!mIsVisibleItemsStale) return mVisibleItems;
1082ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1083ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Refresh the visible items
1084ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems.clear();
1085ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1086ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemsSize = mItems.size();
1087ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl item;
1088ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemsSize; i++) {
1089ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item = mItems.get(i);
109049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (item.isVisible()) mVisibleItems.add(item);
1091ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1092ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1093ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = false;
1094ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1095ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1096ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mVisibleItems;
1097ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1098ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1099ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This method determines which menu items get to be 'action items' that will appear
1101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in an action bar and which items should be 'overflow items' in a secondary menu.
1102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * The rules are as follows:
1103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>Items are considered for inclusion in the order specified within the menu.
1105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * There is a limit of mMaxActionItems as a total count, optionally including the overflow
1106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * menu button itself. This is a soft limit; if an item shares a group ID with an item
1107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * previously included as an action item, the new item will stay with its group and become
1108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * an action item itself even if it breaks the max item count limit. This is done to
1109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit the conceptual complexity of the items presented within an action bar. Only a few
1110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * unrelated concepts should be presented to the user in this space, and groups are treated
1111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * as a single concept.
1112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This
1114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit may be broken by a single item that exceeds the remaining space, but no further
1115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * items may be added. If an item that is part of a group cannot fit within the remaining
1116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * measured width, the entire group will be demoted to overflow. This is done to ensure room
1117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * for navigation and other affordances in the action bar as well as reduce general UI clutter.
1118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>The space freed by demoting a full group cannot be consumed by future menu items.
1120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Once items begin to overflow, all future items become overflow items as well. This is
1121ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to avoid inadvertent reordering that may break the app's intended design.
1122ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void flagActionItems() {
112449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // Important side effect: if getVisibleItems is stale it may refresh,
112549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // which can affect action items staleness.
112649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
112749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
1128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mIsActionItemsStale) {
1129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
1130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1132ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Presenters flag action items as needed.
1133ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean flagged = false;
1134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
1139ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                flagged |= presenter.flagActionItems();
1140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (flagged) {
1144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int itemsSize = visibleItems.size();
1147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            for (int i = 0; i < itemsSize; i++) {
1148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItemImpl item = visibleItems.get(i);
1149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (item.isActionButton()) {
1150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mActionItems.add(item);
1151ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                } else {
1152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mNonActionItems.add(item);
1153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
1154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Nobody flagged anything, everything is a non-action item.
1157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // (This happens during a first pass with no action-item presenters.)
1158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.addAll(getVisibleItems());
1161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = false;
1163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
116549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getActionItems() {
1166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mActionItems;
1168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
117049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getNonActionItems() {
1171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mNonActionItems;
1173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearHeader() {
1176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderIcon = null;
1177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderTitle = null;
1178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderView = null;
1179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
118420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final Drawable icon, final View view) {
1185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Resources r = getResources();
1186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (view != null) {
1188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = view;
1189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using a custom view, then the title and icon aren't used
1191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderTitle = null;
1192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderIcon = null;
1193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (titleRes > 0) {
1195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = r.getText(titleRes);
1196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (title != null) {
1197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = title;
1198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (iconRes > 0) {
12017fa6a00a4600aac591402398c23fea97721adf26Chris Banes                mHeaderIcon = ContextCompat.getDrawable(getContext(), iconRes);
1202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (icon != null) {
1203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderIcon = icon;
1204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using the title or icon, then a custom view isn't used
1207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = null;
1208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of change
1211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
121549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's title. This replaces the header view. Called by the
121649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param title The new title.
1219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
1222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, title, 0, null, null);
1223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
122749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's title. This replaces the header view. Called by the
122849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param titleRes The new title (as a resource ID).
1231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(int titleRes) {
1234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(titleRes, null, 0, null, null);
1235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
123949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's icon. This replaces the header view. Called by the
124049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param icon The new icon.
1243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(Drawable icon) {
1246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, icon, null);
1247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
125149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's icon. This replaces the header view. Called by the
125249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param iconRes The new icon (as a resource ID).
1255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(int iconRes) {
1258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, iconRes, null, null);
1259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
126349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's view. This replaces the title and icon. Called by the
126449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param view The new view.
1267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderViewInt(View view) {
1270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, null, view);
1271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public CharSequence getHeaderTitle() {
1275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderTitle;
1276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Drawable getHeaderIcon() {
1279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderIcon;
1280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public View getHeaderView() {
1283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderView;
1284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Gets the root menu (if this is a submenu, find its root menu).
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
1305002d5bbb223ba6742d1c20a9a87064fbe62cd78fAnatoly Korniltsev    public 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