149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes/*
249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2012 The Android Open Source Project
349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * you may not use this file except in compliance with the License.
649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * You may obtain a copy of the License at
749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
1049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Unless required by applicable law or agreed to in writing, software
1149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * See the License for the specific language governing permissions and
1449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * limitations under the License.
1549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */
16bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
17da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.view.menu;
18bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
19bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.ComponentName;
20bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Context;
21bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Intent;
22ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.pm.PackageManager;
23ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.pm.ResolveInfo;
24ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.res.Configuration;
25ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.res.Resources;
26bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.graphics.drawable.Drawable;
27ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.os.Bundle;
28ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.os.Parcelable;
297fa6a00a4600aac591402398c23fea97721adf26Chris Banesimport android.support.v4.content.ContextCompat;
3030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.view.MenuItemCompat;
31da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
3230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.view.ActionProvider;
3330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenu;
3430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenuItem;
35ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.util.SparseArray;
36ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.view.ContextMenu;
37ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.view.KeyCharacterMap;
38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.KeyEvent;
3930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
4030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.SubMenu;
41bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View;
42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
43ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.lang.ref.WeakReference;
44bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList;
45ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.util.List;
46ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.util.concurrent.CopyOnWriteArrayList;
47bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
48bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/**
4930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell * Implementation of the {@link android.support.v4.internal.view.SupportMenu} interface for creating a
50ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani * standard menu UI.
5189208232f3b5d1451408d787872504a190bc7ee0Chris Banes *
5289208232f3b5d1451408d787872504a190bc7ee0Chris Banes * @hide
53bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
5430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellpublic class MenuBuilder implements SupportMenu {
5520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
56ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String TAG = "MenuBuilder";
57ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String PRESENTER_KEY = "android:menu:presenters";
59ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
60ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview";
61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private static final int[] sCategoryToOrder = new int[]{
63ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            1, /* No category */
64ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            4, /* CONTAINER */
65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            5, /* SYSTEM */
66ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            3, /* SECONDARY */
67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            2, /* ALTERNATIVE */
68ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            0, /* SELECTED_ALTERNATIVE */
69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    };
70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
71ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Context mContext;
7220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
73ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Resources mResources;
74ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
75ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
7620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode() instead of accessing
7720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * this directly.
78ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
79ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mQwertyMode;
80ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
81ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
8220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether the shortcuts should be visible on menus. Use isShortcutsVisible() instead of
8320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * accessing this directly.
84ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
85ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mShortcutsVisible;
86ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
87ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
8820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Callback that will receive the various menu-related events generated by this class. Use
8920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * getCallback to get a reference to the callback.
90ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
91ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private Callback mCallback;
92ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
9420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Contains all of the items for this menu
9520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
96ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mItems;
97ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
9920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Contains only the items that are currently visible.  This will be created/refreshed from
10020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * {@link #getVisibleItems()}
10120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mVisibleItems;
10320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Whether or not the items (or any one item's shown state) has changed since it was last
106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * fetched from {@link #getVisibleItems()}
107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsVisibleItemsStale;
109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Contains only the items that should appear in the Action Bar, if present.
112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mActionItems;
11420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Contains items that should NOT appear in the Action Bar, if present.
117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mNonActionItems;
119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
12120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether or not the items (or any one item's action state) has changed since it was last
12220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * fetched.
123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsActionItemsStale;
125ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
127ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Default value for how added items should show in the action list.
128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
12930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    private int mDefaultShowAsAction = SupportMenuItem.SHOW_AS_ACTION_NEVER;
130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
13220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Current use case is Context Menus: As Views populate the context menu, each one has extra
13320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * information that should be passed along.  This is the current menu info that should be set on
13420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * all items added to this menu.
135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ContextMenu.ContextMenuInfo mCurrentMenuInfo;
137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
13820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
13920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header title for menu types that have a header (context and submenus)
14020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    CharSequence mHeaderTitle;
14220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
14320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
14420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header icon for menu types that have a header and support icons (context)
14520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Drawable mHeaderIcon;
14749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /** Header custom view for menu types that have a header and support custom views (context) */
14849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    View mHeaderView;
14920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
15020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
15149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Contains the state of the View hierarchy for all menu views when the menu
15249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * was frozen.
15320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
15449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private SparseArray<Parcelable> mFrozenViewStates;
155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
15749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Prevents onItemsChanged from doing its junk, useful for batching commands
15849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * that may individually call onItemsChanged.
159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mPreventDispatchingItemsChanged = false;
16120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mItemsChangedWhileDispatchPrevented = false;
163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mOptionalIconsVisible = false;
165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsClosing = false;
167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mTempShortcutItemList = new ArrayList<MenuItemImpl>();
169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private CopyOnWriteArrayList<WeakReference<MenuPresenter>> mPresenters =
171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            new CopyOnWriteArrayList<WeakReference<MenuPresenter>>();
172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Currently expanded menu item; must be collapsed when we clear.
175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuItemImpl mExpandedItem;
177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by menu to notify of close and selection changes.
18089208232f3b5d1451408d787872504a190bc7ee0Chris Banes     * @hide
181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public interface Callback {
18320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        /**
185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * Called when a menu item is selected.
18620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *
187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param menu The menu that is the parent of the item
188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param item The menu item that is selected
189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @return whether the menu item selection was handled
190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         */
191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        /**
194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * Called when the mode of the menu changes (for example, from icon to expanded).
195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         *
196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param menu the menu that has changed modes
197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         */
198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public void onMenuModeChange(MenuBuilder menu);
199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by menu items to execute their associated action
20389208232f3b5d1451408d787872504a190bc7ee0Chris Banes     * @hide
204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public interface ItemInvoker {
206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public boolean invokeItem(MenuItemImpl item);
207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder(Context context) {
210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mContext = context;
211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mResources = context.getResources();
212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems = new ArrayList<MenuItemImpl>();
214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems = new ArrayList<MenuItemImpl>();
216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mActionItems = new ArrayList<MenuItemImpl>();
219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mNonActionItems = new ArrayList<MenuItemImpl>();
220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(true);
223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mDefaultShowAsAction = defaultShowAsAction;
227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
23120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Add a presenter to this menu. This will only hold a WeakReference; you do not need to
23220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * explicitly remove a presenter, but you can using {@link #removeMenuPresenter(MenuPresenter)}.
233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to add
235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void addMenuPresenter(MenuPresenter presenter) {
23749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        addMenuPresenter(presenter, mContext);
23849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
23949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
24049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
24149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Add a presenter to this menu that uses an alternate context for
24249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * inflating menu items. This will only hold a WeakReference; you do not
24349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * need to explicitly remove a presenter, but you can using
24449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * {@link #removeMenuPresenter(MenuPresenter)}.
24549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
24649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param presenter The presenter to add
24749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param menuContext The context used to inflate menu items
24849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
24949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void addMenuPresenter(MenuPresenter presenter, Context menuContext) {
250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPresenters.add(new WeakReference<MenuPresenter>(presenter));
25149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        presenter.initForMenu(menuContext, this);
252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
25620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Remove a presenter from this menu. That presenter will no longer receive notifications of
25720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * updates to this menu's data.
258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to remove
260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeMenuPresenter(MenuPresenter presenter) {
262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter item = ref.get();
264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item == null || item == presenter) {
265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchPresenterUpdate(boolean cleared) {
27149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return;
272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.updateMenuView(cleared);
280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
28549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu,
28649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            MenuPresenter preferredPresenter) {
28749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return false;
288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean result = false;
290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
29149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // Try the preferred presenter first.
29249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (preferredPresenter != null) {
29349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            result = preferredPresenter.onSubMenuSelected(subMenu);
29449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
29549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
300ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (!result) {
301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                result = presenter.onSubMenuSelected(subMenu);
302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return result;
305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchSaveInstanceState(Bundle outState) {
30849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return;
309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    final Parcelable state = presenter.onSaveInstanceState();
320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (state != null) {
321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenterStates.put(id, state);
322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchRestoreInstanceState(Bundle state) {
331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
33349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (presenterStates == null || mPresenters.isEmpty()) return;
334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    Parcelable parcel = presenterStates.get(id);
343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (parcel != null) {
344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenter.onRestoreInstanceState(parcel);
345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void savePresenterStates(Bundle outState) {
352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchSaveInstanceState(outState);
353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restorePresenterStates(Bundle state) {
356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchRestoreInstanceState(state);
357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void saveActionViewStates(Bundle outStates) {
360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = null;
361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
36530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
367ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (viewStates == null) {
368ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    viewStates = new SparseArray<Parcelable>();
369ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
370ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.saveHierarchyState(viewStates);
37130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                if (MenuItemCompat.isActionViewExpanded(item)) {
372ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId());
373ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
374ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
375ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
376ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
377ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.saveActionViewStates(outStates);
378ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
379ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
380ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
381ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (viewStates != null) {
382ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates);
383ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
384ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
385ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
386ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restoreActionViewStates(Bundle states) {
387ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (states == null) {
388ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
389ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
390ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
391ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = states.getSparseParcelableArray(
392ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                getActionViewStatesKey());
393ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
394ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
395ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
396ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
39730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
398ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
399ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.restoreHierarchyState(viewStates);
400ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
401ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
402ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
403ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.restoreActionViewStates(states);
404ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
405ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
406ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
407ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID);
408ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expandedId > 0) {
409ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItem itemToExpand = findItem(expandedId);
410ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (itemToExpand != null) {
41130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                MenuItemCompat.expandActionView(itemToExpand);
412ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
413ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
414ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
415ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
416ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected String getActionViewStatesKey() {
417ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return ACTION_VIEW_STATES_KEY;
418ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
419ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
420ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCallback(Callback cb) {
421ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCallback = cb;
422ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
423ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
424ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
425ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Adds an item to the menu.  The other add methods funnel to this.
426ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
427ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
428ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int ordering = getOrdering(categoryOrder);
429ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
43049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final MenuItemImpl item = createNewMenuItem(group, id, categoryOrder, ordering, title,
43149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                mDefaultShowAsAction);
432ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
433ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCurrentMenuInfo != null) {
434ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Pass along the current menu info
435ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item.setMenuInfo(mCurrentMenuInfo);
436ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
437ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
438ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.add(findInsertIndex(mItems, ordering), item);
439ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
440ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
441ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return item;
442ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
443ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
44449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    // Layoutlib overrides this method to return its custom implementation of MenuItemImpl
44549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private MenuItemImpl createNewMenuItem(int group, int id, int categoryOrder, int ordering,
44649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            CharSequence title, int defaultShowAsAction) {
44749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return new MenuItemImpl(this, group, id, categoryOrder, ordering, title,
44849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                defaultShowAsAction);
44949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
45049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
451ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(CharSequence title) {
452ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, title);
453ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
454ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4556e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
456ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int titleRes) {
457ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, mResources.getString(titleRes));
458ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
459ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4606e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
461ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
462ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, title);
463ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
464ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4656e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
466ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, int title) {
467ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, mResources.getString(title));
468ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
469ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4706e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
471ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(CharSequence title) {
472ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, title);
473ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
474ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4756e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
476ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int titleRes) {
477ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
478ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
479ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4806e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
481ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
482ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
483ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
484ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        item.setSubMenu(subMenu);
485ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
486ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return subMenu;
487ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
488ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4896e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
490ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
491ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
492ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
493ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4946e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
495ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
49620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
497ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        PackageManager pm = mContext.getPackageManager();
498ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final List<ResolveInfo> lri =
499ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
500ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = lri != null ? lri.size() : 0;
501ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
502ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
503ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            removeGroup(group);
504ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
505ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
50620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        for (int i = 0; i < N; i++) {
507ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final ResolveInfo ri = lri.get(i);
508ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            Intent rintent = new Intent(
509ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
510ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            rintent.setComponent(new ComponentName(
511ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.applicationInfo.packageName,
512ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.name));
513ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
514ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIcon(ri.loadIcon(pm))
515ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIntent(rintent);
516ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (outSpecificItems != null && ri.specificIndex >= 0) {
517ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                outSpecificItems[ri.specificIndex] = item;
518ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
519ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
520ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
521ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return N;
522ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
523ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5246e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
525ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItem(int id) {
526ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(findItemIndex(id), true);
527ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
528ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5296e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
530ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeGroup(int group) {
531ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int i = findGroupIndex(group);
532ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
533ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (i >= 0) {
534ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int maxRemovable = mItems.size() - i;
535ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            int numRemoved = 0;
536ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
537ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Don't force update for each one, this method will do it at the end
538ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                removeItemAtInt(i, false);
539ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
540ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
541ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Notify menu views
542ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
543ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
544ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
545ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
546ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
54749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Remove the item at the given index and optionally forces menu views to
54849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * update.
549ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
55049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param index The index of the item to be removed. If this index is
55149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            invalid an exception is thrown.
55249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param updateChildrenOnMenuViews Whether to force update on menu views.
55349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            Please make sure you eventually call this after your batch of
55449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            removals.
555ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
556ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
55749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if ((index < 0) || (index >= mItems.size())) return;
558ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
559ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.remove(index);
560ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
56149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (updateChildrenOnMenuViews) onItemsChanged(true);
562ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
563ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
564ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItemAt(int index) {
565ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(index, true);
566ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
567ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
568ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearAll() {
569ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = true;
570ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clear();
571ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clearHeader();
572ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
573ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItemsChangedWhileDispatchPrevented = false;
574ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
575ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
576ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5776e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
578ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clear() {
579ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mExpandedItem != null) {
580ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            collapseItemActionView(mExpandedItem);
581ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
582ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.clear();
583ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
584ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
585ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
586ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
587ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setExclusiveItemChecked(MenuItem item) {
588ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int group = item.getGroupId();
589ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
590ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
591ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
592ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl curItem = mItems.get(i);
593ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (curItem.getGroupId() == group) {
59449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (!curItem.isExclusiveCheckable()) continue;
59549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (!curItem.isCheckable()) continue;
596ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
597ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Check the item meant to be checked, uncheck the others (that are in the group)
598ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                curItem.setCheckedInt(curItem == item);
599ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
600ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
601ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
602ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6036e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
604ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
605ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
606ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
607ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
608ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
609ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
610ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setExclusiveCheckable(exclusive);
611ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setCheckable(checkable);
612ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
613ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
614ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
615ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6166e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
617ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupVisible(int group, boolean visible) {
618ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
619ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
62049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
62149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // than setVisible and at the end notify of items being changed
622ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
623ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean changedAtLeastOneItem = false;
624ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
625ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
626ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
62749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
628ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
629ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
630ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
63149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (changedAtLeastOneItem) onItemsChanged(true);
632ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
633ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6346e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
635ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupEnabled(int group, boolean enabled) {
636ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
637ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
638ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
639ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
640ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
641ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setEnabled(enabled);
642ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
643ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
644ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
645ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6466e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
647ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean hasVisibleItems() {
648ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
649bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
650ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
651ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
652ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.isVisible()) {
653ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return true;
654ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
655ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
656bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
657ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
658ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
659bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
6606e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
661ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem findItem(int id) {
662ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
663ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
664ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
665ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
666ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
667ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (item.hasSubMenu()) {
668ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItem possibleItem = item.getSubMenu().findItem(id);
669bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
670ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (possibleItem != null) {
671ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    return possibleItem;
672ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
673ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
674ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
675bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
676ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
677ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
678bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
679ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findItemIndex(int id) {
680ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
681bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
682ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
683ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
684ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
685ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
686ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
687ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
688bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
689ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
690ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
691bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
692ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group) {
693ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findGroupIndex(group, 0);
694ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
695bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
696ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group, int start) {
697ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
698bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
699ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (start < 0) {
700ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            start = 0;
701ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
702ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
703ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = start; i < size; i++) {
704ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = mItems.get(i);
705ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
706ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
707ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
708ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
709ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
710ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
711ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
712ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
713ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7146e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
715ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int size() {
716ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.size();
717ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
718ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7196e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
720ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem getItem(int index) {
721ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.get(index);
722ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
723ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7246e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
725ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutKey(int keyCode, KeyEvent event) {
726ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findItemWithShortcutForKey(keyCode, event) != null;
727ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
728ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7296e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
730ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setQwertyMode(boolean isQwerty) {
731ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mQwertyMode = isQwerty;
732ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
733ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
734ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
735ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
736ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
73749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Returns the ordering across all items. This will grab the category from
73849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the upper bits, find out how to order the category with respect to other
73949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * categories, and combine it with the lower bits.
740ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
74149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param categoryOrder The category order for a particular item (if it has
74249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            not been or/add with a category, the default category is
74349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            assumed).
74449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return An ordering integer that can be used to order this item across
74549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *         all the items (even from other categories).
746ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
747ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int getOrdering(int categoryOrder) {
748ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
749ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
750ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (index < 0 || index >= sCategoryToOrder.length) {
751ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            throw new IllegalArgumentException("order does not contain a valid category.");
752ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
753ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
754ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
755ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
756b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
757b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
758ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return whether the menu shortcuts are in qwerty mode or not
759b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
760ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean isQwertyMode() {
761ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mQwertyMode;
762ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
763b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
764b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
76520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets whether the shortcuts should be visible on menus.  Devices without hardware key input
76620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * will never make shortcuts visible even if this method is passed 'true'.
767b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     *
76820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param shortcutsVisible Whether shortcuts should be visible (if true and a menu item does not
76920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         have a shortcut defined, that item will still NOT show a shortcut)
770ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
771ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setShortcutsVisible(boolean shortcutsVisible) {
77220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mShortcutsVisible == shortcutsVisible) {
77320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
77420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
775ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
776ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(shortcutsVisible);
777ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
778ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
779ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
780ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setShortcutsVisibleInner(boolean shortcutsVisible) {
781ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mShortcutsVisible = shortcutsVisible
782ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS
78307a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes                && mResources.getBoolean(R.bool.abc_config_showMenuShortcutsWhenKeyboardPresent);
784ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
785ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
786ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
787ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return Whether shortcuts should be visible on menus.
788ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
789ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutsVisible() {
790ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mShortcutsVisible;
791ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
792ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
793ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Resources getResources() {
794ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mResources;
795ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
796ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
797ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Context getContext() {
798ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mContext;
799ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
800ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
801ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) {
802ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mCallback != null && mCallback.onMenuItemSelected(menu, item);
803ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
804ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
805ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
806ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Dispatch a mode change event to this menu's callback.
807ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
808ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void changeMenuMode() {
809ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCallback != null) {
810ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mCallback.onMenuModeChange(this);
811ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
812ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
813ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
814ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
815ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = items.size() - 1; i >= 0; i--) {
816ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = items.get(i);
817ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getOrdering() <= ordering) {
818ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i + 1;
819ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
820ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
821ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
822ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return 0;
823ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
824ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
8256e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
826ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
827ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
828ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
829ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean handled = false;
830ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
831ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (item != null) {
832ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            handled = performItemAction(item, flags);
833ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
834ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
835ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
836ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            close(true);
837ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
838ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
839ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return handled;
840ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
841ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
842ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
843ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This function will return all the menu and sub-menu items that can
844ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * be directly (the shortcut directly corresponds) and indirectly
845ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * (the ALT-enabled char corresponds to the shortcut) associated
846ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * with the keyCode.
847ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8486e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
849ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
850ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
851ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
852ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
853ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
854ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
855ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // The delete key is not mapped to '\b' so we treat it specially
856ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
857ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
858ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
859ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
860ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose shortcut is this key.
861ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
862ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
863ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
864ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
86549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                ((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
866ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
86749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
868ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
86949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  (shortcutChar != 0) &&
87049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  (shortcutChar == possibleChars.meta[0]
87149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                      || shortcutChar == possibleChars.meta[2]
87249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                      || (qwerty && shortcutChar == '\b' &&
87349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                          keyCode == KeyEvent.KEYCODE_DEL)) &&
87449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                  item.isEnabled()) {
875ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                items.add(item);
876ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
877ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
878ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
879ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
880ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
881ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * We want to return the menu item associated with the key, but if there is no
882ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * ambiguity (i.e. there is only one menu item corresponding to the key) we want
883ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to return it even if it's not an exact match; this allow the user to
884ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * _not_ use the ALT key for example, making the use of shortcuts slightly more
885ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
886ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
887ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
888ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * On the other hand, if two (or more) shortcuts corresponds to the same key,
889ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * we have to only return the exact match.
890ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8916e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
892ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
893ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get all items that can be associated directly or indirectly with the keyCode
894ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        ArrayList<MenuItemImpl> items = mTempShortcutItemList;
895ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        items.clear();
896ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        findItemsWithShortcutForKey(items, keyCode, event);
897ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
898ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (items.isEmpty()) {
899ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return null;
900ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
901ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
902ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
903ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
904ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
905ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        event.getKeyData(possibleChars);
906ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
907ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we have only one element, we can safely returns it
908ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = items.size();
909ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (size == 1) {
910ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.get(0);
911ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
912ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
913ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
914ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we found more than one item associated with the key,
915ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // we have to return the exact match
916ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
917ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = items.get(i);
918ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
919ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    item.getNumericShortcut();
920ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((shortcutChar == possibleChars.meta[0] &&
921ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) == 0)
92249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                || (shortcutChar == possibleChars.meta[2] &&
923ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) != 0)
92449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                || (qwerty && shortcutChar == '\b' &&
925ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    keyCode == KeyEvent.KEYCODE_DEL)) {
926ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
927ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
928ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
929ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
930ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
931ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9326e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
933ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performIdentifierAction(int id, int flags) {
934ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose identifier is the id.
935ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return performItemAction(findItem(id), flags);
936ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
937ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
938ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performItemAction(MenuItem item, int flags) {
93949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return performItemAction(item, null, flags);
94049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
94149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
94249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public boolean performItemAction(MenuItem item, MenuPresenter preferredPresenter, int flags) {
943ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl itemImpl = (MenuItemImpl) item;
944ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
945ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl == null || !itemImpl.isEnabled()) {
946ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return false;
947ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
948ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
949ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean invoked = itemImpl.invoke();
950ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
95130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        final ActionProvider provider = itemImpl.getSupportActionProvider();
952ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean providerHasSubMenu = provider != null && provider.hasSubMenu();
953ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl.hasCollapsibleActionView()) {
954ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            invoked |= itemImpl.expandActionView();
95549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (invoked) close(true);
956ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else if (itemImpl.hasSubMenu() || providerHasSubMenu) {
957ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            close(false);
958ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
959ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (!itemImpl.hasSubMenu()) {
960ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemImpl.setSubMenu(new SubMenuBuilder(getContext(), this, itemImpl));
961ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
962ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
963ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final SubMenuBuilder subMenu = (SubMenuBuilder) itemImpl.getSubMenu();
964ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (providerHasSubMenu) {
965ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                provider.onPrepareSubMenu(subMenu);
966ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
96749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            invoked |= dispatchSubMenuSelected(subMenu, preferredPresenter);
96849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (!invoked) close(true);
969ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
970ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
971ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                close(true);
972ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
973ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
974ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
975ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return invoked;
976ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
977ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
978ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
979ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Closes the visible menu.
980ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
98149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param allMenusAreClosing Whether the menus are completely closing (true),
98249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            or whether there is another menu coming in this menu's place
98349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            (false). For example, if the menu is closing because a
98449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            sub menu is about to be shown, <var>allMenusAreClosing</var>
98549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *            is false.
986ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
98749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public final void close(boolean allMenusAreClosing) {
98849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mIsClosing) return;
989ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
990ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = true;
991ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
992ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
993ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
994ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
995ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
996ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.onCloseMenu(this, allMenusAreClosing);
997ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
998ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
999ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = false;
1000ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1001ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
10026e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
1003ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void close() {
1004ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        close(true);
1005ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1006ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1007ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1008ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called when an item is added or removed.
1009ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
101049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param structureChanged true if the menu structure changed,
101149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *                         false if only item properties changed.
101249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *                         (Visibility is a structural property since it affects layout.)
1013ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
101449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void onItemsChanged(boolean structureChanged) {
1015ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mPreventDispatchingItemsChanged) {
1016ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (structureChanged) {
1017ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mIsVisibleItemsStale = true;
1018ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mIsActionItemsStale = true;
1019ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1020ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1021ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            dispatchPresenterUpdate(structureChanged);
1022ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1023ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = true;
1024ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1025ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1026ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1027ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
102849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Stop dispatching item changed events to presenters until
102949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * {@link #startDispatchingItemsChanged()} is called. Useful when
103049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * many menu operations are going to be performed as a batch.
1031ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1032ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void stopDispatchingItemsChanged() {
1033ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mPreventDispatchingItemsChanged) {
1034ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPreventDispatchingItemsChanged = true;
1035ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = false;
1036ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1037ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1038ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1039ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void startDispatchingItemsChanged() {
1040ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
1041ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1042ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mItemsChangedWhileDispatchPrevented) {
1043ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = false;
1044ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
1045ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1046ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1047ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1048ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1049ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by {@link MenuItemImpl} when its visible flag is changed.
105020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1051ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param item The item that has gone through a visibility change.
1052b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
1053ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemVisibleChanged(MenuItemImpl item) {
1054ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of items being changed
1055ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
1056ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
1057ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1058ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1059ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1060ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by {@link MenuItemImpl} when its action request status is changed.
106120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1062ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param item The item that has gone through a change in action request status.
1063ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1064ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemActionRequestChanged(MenuItemImpl item) {
1065ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of items being changed
1066ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1067ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
1068ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1069ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
107049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getVisibleItems() {
107149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (!mIsVisibleItemsStale) return mVisibleItems;
1072ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1073ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Refresh the visible items
1074ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems.clear();
1075ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1076ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemsSize = mItems.size();
1077ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl item;
1078ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemsSize; i++) {
1079ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item = mItems.get(i);
108049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (item.isVisible()) mVisibleItems.add(item);
1081ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1082ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1083ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = false;
1084ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1085ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1086ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mVisibleItems;
1087ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1088ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1089ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1090ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This method determines which menu items get to be 'action items' that will appear
1091ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in an action bar and which items should be 'overflow items' in a secondary menu.
1092ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * The rules are as follows:
1093ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1094ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>Items are considered for inclusion in the order specified within the menu.
1095ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * There is a limit of mMaxActionItems as a total count, optionally including the overflow
1096ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * menu button itself. This is a soft limit; if an item shares a group ID with an item
1097ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * previously included as an action item, the new item will stay with its group and become
1098ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * an action item itself even if it breaks the max item count limit. This is done to
1099ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit the conceptual complexity of the items presented within an action bar. Only a few
1100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * unrelated concepts should be presented to the user in this space, and groups are treated
1101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * as a single concept.
1102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This
1104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit may be broken by a single item that exceeds the remaining space, but no further
1105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * items may be added. If an item that is part of a group cannot fit within the remaining
1106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * measured width, the entire group will be demoted to overflow. This is done to ensure room
1107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * for navigation and other affordances in the action bar as well as reduce general UI clutter.
1108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>The space freed by demoting a full group cannot be consumed by future menu items.
1110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Once items begin to overflow, all future items become overflow items as well. This is
1111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to avoid inadvertent reordering that may break the app's intended design.
1112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void flagActionItems() {
111449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // Important side effect: if getVisibleItems is stale it may refresh,
111549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // which can affect action items staleness.
111649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
111749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
1118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mIsActionItemsStale) {
1119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
1120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1121ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1122ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Presenters flag action items as needed.
1123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean flagged = false;
1124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1125ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1127ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
1129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                flagged |= presenter.flagActionItems();
1130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1132ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1133ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (flagged) {
1134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int itemsSize = visibleItems.size();
1137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            for (int i = 0; i < itemsSize; i++) {
1138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItemImpl item = visibleItems.get(i);
1139ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (item.isActionButton()) {
1140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mActionItems.add(item);
1141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                } else {
1142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mNonActionItems.add(item);
1143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
1144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Nobody flagged anything, everything is a non-action item.
1147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // (This happens during a first pass with no action-item presenters.)
1148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.addAll(getVisibleItems());
1151ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = false;
1153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
115549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getActionItems() {
1156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mActionItems;
1158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
116049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ArrayList<MenuItemImpl> getNonActionItems() {
1161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mNonActionItems;
1163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearHeader() {
1166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderIcon = null;
1167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderTitle = null;
1168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderView = null;
1169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
117420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final Drawable icon, final View view) {
1175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Resources r = getResources();
1176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (view != null) {
1178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = view;
1179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using a custom view, then the title and icon aren't used
1181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderTitle = null;
1182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderIcon = null;
1183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (titleRes > 0) {
1185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = r.getText(titleRes);
1186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (title != null) {
1187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = title;
1188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (iconRes > 0) {
11917fa6a00a4600aac591402398c23fea97721adf26Chris Banes                mHeaderIcon = ContextCompat.getDrawable(getContext(), iconRes);
1192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (icon != null) {
1193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderIcon = icon;
1194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using the title or icon, then a custom view isn't used
1197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = null;
1198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of change
1201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
120549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's title. This replaces the header view. Called by the
120649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param title The new title.
1209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
1212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, title, 0, null, null);
1213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
121749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's title. This replaces the header view. Called by the
121849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param titleRes The new title (as a resource ID).
1221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(int titleRes) {
1224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(titleRes, null, 0, null, null);
1225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
122949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's icon. This replaces the header view. Called by the
123049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param icon The new icon.
1233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(Drawable icon) {
1236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, icon, null);
1237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
124149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's icon. This replaces the header view. Called by the
124249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param iconRes The new icon (as a resource ID).
1245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(int iconRes) {
1248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, iconRes, null, null);
1249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
125349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the header's view. This replaces the title and icon. Called by the
125449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * builder-style methods of subclasses.
1255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param view The new view.
1257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderViewInt(View view) {
1260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, null, view);
1261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public CharSequence getHeaderTitle() {
1265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderTitle;
1266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Drawable getHeaderIcon() {
1269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderIcon;
1270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public View getHeaderView() {
1273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderView;
1274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Gets the root menu (if this is a submenu, find its root menu).
127820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return The root menu.
1280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder getRootMenu() {
1282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
128649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the current menu info that is set on all items added to this menu
128749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * (until this is called again with different menu info, in which case that
128849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * one will be added to all subsequent item additions).
1289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param menuInfo The extra menu information to add.
1291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCurrentMenuInfo(ContextMenu.ContextMenuInfo menuInfo) {
1293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCurrentMenuInfo = menuInfo;
1294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setOptionalIconsVisible(boolean visible) {
1297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mOptionalIconsVisible = visible;
1298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1300ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean getOptionalIconsVisible() {
1301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mOptionalIconsVisible;
1302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean expandItemActionView(MenuItemImpl item) {
130549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty()) return false;
1306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean expanded = false;
1308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
1310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if ((expanded = presenter.expandItemActionView(this, item))) {
1315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                break;
1316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
1319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expanded) {
1321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedItem = item;
1322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return expanded;
1324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean collapseItemActionView(MenuItemImpl item) {
132749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mPresenters.isEmpty() || mExpandedItem != item) return false;
1328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean collapsed = false;
1330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
1332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if ((collapsed = presenter.collapseItemActionView(this, item))) {
1337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                break;
1338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
1341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (collapsed) {
1343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedItem = null;
1344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return collapsed;
1346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItemImpl getExpandedItem() {
1349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mExpandedItem;
1350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1351bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell}
1352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1353