MenuBuilder.java revision 6e6abe6eb358db4c3932752249c8ac61dd3dab21
1bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell// Copyright 2012 Google Inc. All Rights Reserved.
2bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
3da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.view.menu;
4bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
5bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.ComponentName;
6bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Context;
7bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Intent;
8ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.pm.PackageManager;
9ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.pm.ResolveInfo;
10ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.res.Configuration;
11ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.content.res.Resources;
12bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.graphics.drawable.Drawable;
13ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.os.Bundle;
14ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.os.Parcelable;
1530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.view.MenuItemCompat;
16da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
1730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.view.ActionProvider;
1830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenu;
1930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.support.v4.internal.view.SupportMenuItem;
20ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.util.SparseArray;
21ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.view.ContextMenu;
22ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport android.view.KeyCharacterMap;
23bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.KeyEvent;
2430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
2530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.SubMenu;
26bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View;
27bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
28ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.lang.ref.WeakReference;
29bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList;
30ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.util.List;
31ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewaniimport java.util.concurrent.CopyOnWriteArrayList;
32bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
33bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/**
3430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell * Implementation of the {@link android.support.v4.internal.view.SupportMenu} interface for creating a
35ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani * standard menu UI.
36bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
3730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellpublic class MenuBuilder implements SupportMenu {
3820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
39ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String TAG = "MenuBuilder";
40ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
41ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String PRESENTER_KEY = "android:menu:presenters";
42ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
43ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview";
44ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private static final int[] sCategoryToOrder = new int[]{
46ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            1, /* No category */
47ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            4, /* CONTAINER */
48ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            5, /* SYSTEM */
49ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            3, /* SECONDARY */
50ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            2, /* ALTERNATIVE */
51ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            0, /* SELECTED_ALTERNATIVE */
52ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    };
53ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
54ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Context mContext;
5520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
56ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Resources mResources;
57ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
5920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode() instead of accessing
6020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * this directly.
61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
62ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mQwertyMode;
63ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
64ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
6520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether the shortcuts should be visible on menus. Use isShortcutsVisible() instead of
6620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * accessing this directly.
67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
68ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mShortcutsVisible;
69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
7120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Callback that will receive the various menu-related events generated by this class. Use
7220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * getCallback to get a reference to the callback.
73ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
74ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private Callback mCallback;
75ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
7720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Contains all of the items for this menu
7820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
79ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mItems;
80ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
8120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
8220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Contains only the items that are currently visible.  This will be created/refreshed from
8320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * {@link #getVisibleItems()}
8420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
85ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mVisibleItems;
8620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
87ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
88ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Whether or not the items (or any one item's shown state) has changed since it was last
89ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * fetched from {@link #getVisibleItems()}
90ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
91ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsVisibleItemsStale;
92ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
93ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
94ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Contains only the items that should appear in the Action Bar, if present.
95ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
96ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mActionItems;
9720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
98ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
99ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Contains items that should NOT appear in the Action Bar, if present.
100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mNonActionItems;
102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
10420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether or not the items (or any one item's action state) has changed since it was last
10520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * fetched.
106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsActionItemsStale;
108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Default value for how added items should show in the action list.
111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
11230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    private int mDefaultShowAsAction = SupportMenuItem.SHOW_AS_ACTION_NEVER;
113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
11520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Current use case is Context Menus: As Views populate the context menu, each one has extra
11620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * information that should be passed along.  This is the current menu info that should be set on
11720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * all items added to this menu.
118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ContextMenu.ContextMenuInfo mCurrentMenuInfo;
120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
12120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
12220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header title for menu types that have a header (context and submenus)
12320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    CharSequence mHeaderTitle;
12520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
12620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
12720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header icon for menu types that have a header and support icons (context)
12820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Drawable mHeaderIcon;
13020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
13120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
13220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header custom view for menu types that have a header and support custom views (context)
13320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    View mHeaderView;
135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
13720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Prevents onItemsChanged from doing its junk, useful for batching commands that may
13820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * individually call onItemsChanged.
139ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mPreventDispatchingItemsChanged = false;
14120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mItemsChangedWhileDispatchPrevented = false;
143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mOptionalIconsVisible = false;
145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsClosing = false;
147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mTempShortcutItemList = new ArrayList<MenuItemImpl>();
149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private CopyOnWriteArrayList<WeakReference<MenuPresenter>> mPresenters =
151ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            new CopyOnWriteArrayList<WeakReference<MenuPresenter>>();
152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Currently expanded menu item; must be collapsed when we clear.
155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuItemImpl mExpandedItem;
157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by menu to notify of close and selection changes.
160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public interface Callback {
16220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        /**
164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * Called when a menu item is selected.
16520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *
166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param menu The menu that is the parent of the item
167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param item The menu item that is selected
168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @return whether the menu item selection was handled
169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         */
170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        /**
173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * Called when the mode of the menu changes (for example, from icon to expanded).
174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         *
175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param menu the menu that has changed modes
176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         */
177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public void onMenuModeChange(MenuBuilder menu);
178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by menu items to execute their associated action
182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public interface ItemInvoker {
18420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public boolean invokeItem(MenuItemImpl item);
186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder(Context context) {
189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mContext = context;
190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mResources = context.getResources();
191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems = new ArrayList<MenuItemImpl>();
193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems = new ArrayList<MenuItemImpl>();
195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mActionItems = new ArrayList<MenuItemImpl>();
198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mNonActionItems = new ArrayList<MenuItemImpl>();
199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(true);
202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mDefaultShowAsAction = defaultShowAsAction;
206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
21020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Add a presenter to this menu. This will only hold a WeakReference; you do not need to
21120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * explicitly remove a presenter, but you can using {@link #removeMenuPresenter(MenuPresenter)}.
212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to add
214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void addMenuPresenter(MenuPresenter presenter) {
216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPresenters.add(new WeakReference<MenuPresenter>(presenter));
217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        presenter.initForMenu(mContext, this);
218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
22220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Remove a presenter from this menu. That presenter will no longer receive notifications of
22320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * updates to this menu's data.
224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to remove
226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeMenuPresenter(MenuPresenter presenter) {
228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter item = ref.get();
230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item == null || item == presenter) {
231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchPresenterUpdate(boolean cleared) {
23720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty()) {
23820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
23920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.updateMenuView(cleared);
248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) {
25420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty()) {
25520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return false;
25620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean result = false;
259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (!result) {
265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                result = presenter.onSubMenuSelected(subMenu);
266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return result;
269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchSaveInstanceState(Bundle outState) {
27220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty()) {
27320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
27420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    final Parcelable state = presenter.onSaveInstanceState();
286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (state != null) {
287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenterStates.put(id, state);
288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchRestoreInstanceState(Bundle state) {
297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
29920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (presenterStates == null || mPresenters.isEmpty()) {
30020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
30120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    Parcelable parcel = presenterStates.get(id);
311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (parcel != null) {
312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenter.onRestoreInstanceState(parcel);
313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void savePresenterStates(Bundle outState) {
320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchSaveInstanceState(outState);
321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restorePresenterStates(Bundle state) {
324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchRestoreInstanceState(state);
325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void saveActionViewStates(Bundle outStates) {
328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = null;
329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
33330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (viewStates == null) {
336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    viewStates = new SparseArray<Parcelable>();
337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.saveHierarchyState(viewStates);
33930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                if (MenuItemCompat.isActionViewExpanded(item)) {
340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId());
341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.saveActionViewStates(outStates);
346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (viewStates != null) {
350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates);
351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restoreActionViewStates(Bundle states) {
355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (states == null) {
356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = states.getSparseParcelableArray(
360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                getActionViewStatesKey());
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                v.restoreHierarchyState(viewStates);
368ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
369ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
370ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
371ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.restoreActionViewStates(states);
372ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
373ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
374ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
375ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID);
376ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expandedId > 0) {
377ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItem itemToExpand = findItem(expandedId);
378ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (itemToExpand != null) {
37930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                MenuItemCompat.expandActionView(itemToExpand);
380ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
381ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
382ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
383ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
384ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected String getActionViewStatesKey() {
385ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return ACTION_VIEW_STATES_KEY;
386ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
387ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
388ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCallback(Callback cb) {
389ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCallback = cb;
390ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
391ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
392ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
393ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Adds an item to the menu.  The other add methods funnel to this.
394ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
395ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
396ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int ordering = getOrdering(categoryOrder);
397ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
398ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder,
399ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                ordering, title, mDefaultShowAsAction);
400ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
401ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCurrentMenuInfo != null) {
402ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Pass along the current menu info
403ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item.setMenuInfo(mCurrentMenuInfo);
404ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
405ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
406ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.add(findInsertIndex(mItems, ordering), item);
407ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
408ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
409ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return item;
410ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
411ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4126e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
413ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(CharSequence title) {
414ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, title);
415ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
416ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4176e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
418ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int titleRes) {
419ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, mResources.getString(titleRes));
420ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
421ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4226e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
423ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
424ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, title);
425ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
426ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4276e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
428ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, int title) {
429ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, mResources.getString(title));
430ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
431ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4326e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
433ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(CharSequence title) {
434ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, title);
435ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
436ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4376e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
438ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int titleRes) {
439ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
440ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
441ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4426e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
443ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
444ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
445ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
446ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        item.setSubMenu(subMenu);
447ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
448ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return subMenu;
449ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
450ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4516e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
452ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
453ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
454ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
455ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4566e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
457ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
45820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
459ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        PackageManager pm = mContext.getPackageManager();
460ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final List<ResolveInfo> lri =
461ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
462ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = lri != null ? lri.size() : 0;
463ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
464ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
465ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            removeGroup(group);
466ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
467ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
46820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        for (int i = 0; i < N; i++) {
469ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final ResolveInfo ri = lri.get(i);
470ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            Intent rintent = new Intent(
471ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
472ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            rintent.setComponent(new ComponentName(
473ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.applicationInfo.packageName,
474ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.name));
475ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
476ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIcon(ri.loadIcon(pm))
477ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIntent(rintent);
478ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (outSpecificItems != null && ri.specificIndex >= 0) {
479ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                outSpecificItems[ri.specificIndex] = item;
480ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
481ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
482ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
483ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return N;
484ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
485ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4866e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
487ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItem(int id) {
488ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(findItemIndex(id), true);
489ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
490ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4916e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
492ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeGroup(int group) {
493ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int i = findGroupIndex(group);
494ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
495ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (i >= 0) {
496ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int maxRemovable = mItems.size() - i;
497ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            int numRemoved = 0;
498ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
499ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Don't force update for each one, this method will do it at the end
500ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                removeItemAtInt(i, false);
501ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
502ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
503ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Notify menu views
504ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
505ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
506ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
507ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
508ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
50920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Remove the item at the given index and optionally forces menu views to update.
510ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
51120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param index                     The index of the item to be removed. If this index is
51220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                                  invalid an exception is thrown.
51320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param updateChildrenOnMenuViews Whether to force update on menu views. Please make sure you
51420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                                  eventually call this after your batch of removals.
515ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
516ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
51720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if ((index < 0) || (index >= mItems.size())) {
51820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
51920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
520ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
521ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.remove(index);
522ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
52320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (updateChildrenOnMenuViews) {
52420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            onItemsChanged(true);
52520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
526ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
527ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
528ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItemAt(int index) {
529ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(index, true);
530ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
531ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
532ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearAll() {
533ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = true;
534ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clear();
535ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clearHeader();
536ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
537ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItemsChangedWhileDispatchPrevented = false;
538ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
539ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
540ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5416e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
542ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clear() {
543ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mExpandedItem != null) {
544ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            collapseItemActionView(mExpandedItem);
545ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
546ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.clear();
547ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
548ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
549ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
550ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
551ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setExclusiveItemChecked(MenuItem item) {
552ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int group = item.getGroupId();
553ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
554ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
555ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
556ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl curItem = mItems.get(i);
557ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (curItem.getGroupId() == group) {
55820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (!curItem.isExclusiveCheckable()) {
55920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    continue;
56020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
56120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (!curItem.isCheckable()) {
56220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    continue;
56320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
564ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
565ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Check the item meant to be checked, uncheck the others (that are in the group)
566ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                curItem.setCheckedInt(curItem == item);
567ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
568ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
569ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
570ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5716e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
572ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
573ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
574ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
575ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
576ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
577ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
578ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setExclusiveCheckable(exclusive);
579ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setCheckable(checkable);
580ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
581ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
582ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
583ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5846e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
585ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupVisible(int group, boolean visible) {
586ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
587ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
58820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        // We handle the notification of items being changed ourselves, so we use setVisibleInt
58920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        // rather than setVisible and at the end notify of items being changed
590ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
591ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean changedAtLeastOneItem = false;
592ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
593ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
594ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
59520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (item.setVisibleInt(visible)) {
59620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    changedAtLeastOneItem = true;
59720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
598ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
599ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
600ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
60120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (changedAtLeastOneItem) {
60220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            onItemsChanged(true);
60320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
604ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
605ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6066e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
607ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupEnabled(int group, boolean enabled) {
608ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
609ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
610ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
611ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
612ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
613ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setEnabled(enabled);
614ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
615ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
616ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
617ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6186e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
619ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean hasVisibleItems() {
620ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
621bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
622ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
623ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
624ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.isVisible()) {
625ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return true;
626ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
627ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
628bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
629ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
630ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
631bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
6326e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
633ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem findItem(int id) {
634ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
635ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
636ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
637ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
638ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
639ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (item.hasSubMenu()) {
640ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItem possibleItem = item.getSubMenu().findItem(id);
641bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
642ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (possibleItem != null) {
643ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    return possibleItem;
644ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
645ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
646ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
647bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
648ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
649ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
650bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
651ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findItemIndex(int id) {
652ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
653bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
654ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
655ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
656ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
657ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
658ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
659ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
660bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
661ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
662ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
663bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
664ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group) {
665ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findGroupIndex(group, 0);
666ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
667bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
668ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group, int start) {
669ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
670bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
671ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (start < 0) {
672ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            start = 0;
673ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
674ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
675ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = start; i < size; i++) {
676ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = mItems.get(i);
677ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
678ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
679ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
680ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
681ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
682ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
683ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
684ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
685ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6866e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
687ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int size() {
688ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.size();
689ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
690ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6916e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
692ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem getItem(int index) {
693ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.get(index);
694ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
695ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6966e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
697ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutKey(int keyCode, KeyEvent event) {
698ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findItemWithShortcutForKey(keyCode, event) != null;
699ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
700ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7016e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
702ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setQwertyMode(boolean isQwerty) {
703ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mQwertyMode = isQwerty;
704ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
705ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
706ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
707ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
708ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
70920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Returns the ordering across all items. This will grab the category from the upper bits, find
71020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * out how to order the category with respect to other categories, and combine it with the lower
71120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * bits.
712ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
71320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param categoryOrder The category order for a particular item (if it has not been or/add with
71420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                      a category, the default category is assumed).
71520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return An ordering integer that can be used to order this item across all the items (even
71620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *         from other categories).
717ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
718ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int getOrdering(int categoryOrder) {
719ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
720ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
721ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (index < 0 || index >= sCategoryToOrder.length) {
722ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            throw new IllegalArgumentException("order does not contain a valid category.");
723ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
724ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
725ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
726ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
727b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
728b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
729ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return whether the menu shortcuts are in qwerty mode or not
730b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
731ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean isQwertyMode() {
732ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mQwertyMode;
733ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
734b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
735b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
73620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets whether the shortcuts should be visible on menus.  Devices without hardware key input
73720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * will never make shortcuts visible even if this method is passed 'true'.
738b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     *
73920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param shortcutsVisible Whether shortcuts should be visible (if true and a menu item does not
74020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         have a shortcut defined, that item will still NOT show a shortcut)
741ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
742ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setShortcutsVisible(boolean shortcutsVisible) {
74320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mShortcutsVisible == shortcutsVisible) {
74420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
74520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
746ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
747ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(shortcutsVisible);
748ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
749ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
750ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
751ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setShortcutsVisibleInner(boolean shortcutsVisible) {
752ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mShortcutsVisible = shortcutsVisible
753ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS
754ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                && mResources.getBoolean(R.bool.config_showMenuShortcutsWhenKeyboardPresent);
755ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
756ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
757ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
758ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return Whether shortcuts should be visible on menus.
759ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
760ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutsVisible() {
761ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mShortcutsVisible;
762ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
763ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
764ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Resources getResources() {
765ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mResources;
766ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
767ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
768ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Context getContext() {
769ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mContext;
770ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
771ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
772ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) {
773ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mCallback != null && mCallback.onMenuItemSelected(menu, item);
774ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
775ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
776ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
777ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Dispatch a mode change event to this menu's callback.
778ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
779ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void changeMenuMode() {
780ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCallback != null) {
781ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mCallback.onMenuModeChange(this);
782ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
783ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
784ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
785ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
786ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = items.size() - 1; i >= 0; i--) {
787ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = items.get(i);
788ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getOrdering() <= ordering) {
789ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i + 1;
790ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
791ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
792ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
793ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return 0;
794ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
795ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7966e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
797ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
798ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
799ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
800ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean handled = false;
801ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
802ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (item != null) {
803ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            handled = performItemAction(item, flags);
804ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
805ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
806ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
807ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            close(true);
808ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
809ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
810ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return handled;
811ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
812ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
813ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
814ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This function will return all the menu and sub-menu items that can
815ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * be directly (the shortcut directly corresponds) and indirectly
816ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * (the ALT-enabled char corresponds to the shortcut) associated
817ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * with the keyCode.
818ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8196e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
820ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
821ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
822ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
823ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
824ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
825ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
826ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // The delete key is not mapped to '\b' so we treat it specially
827ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
828ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
829ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
830ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
831ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose shortcut is this key.
832ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
833ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
834ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
835ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
83620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                ((MenuBuilder) item.getSubMenu())
83720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        .findItemsWithShortcutForKey(items, keyCode, event);
838ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
83920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final char shortcutChar = qwerty ? item.getAlphabeticShortcut()
84020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    : item.getNumericShortcut();
841ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
842ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (shortcutChar != 0) &&
843ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (shortcutChar == possibleChars.meta[0]
844ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                            || shortcutChar == possibleChars.meta[2]
845ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                            || (qwerty && shortcutChar == '\b' &&
846ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                            keyCode == KeyEvent.KEYCODE_DEL)) &&
847ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    item.isEnabled()) {
848ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                items.add(item);
849ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
850ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
851ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
852ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
853ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
854ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * We want to return the menu item associated with the key, but if there is no
855ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * ambiguity (i.e. there is only one menu item corresponding to the key) we want
856ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to return it even if it's not an exact match; this allow the user to
857ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * _not_ use the ALT key for example, making the use of shortcuts slightly more
858ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
859ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
860ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
861ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * On the other hand, if two (or more) shortcuts corresponds to the same key,
862ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * we have to only return the exact match.
863ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8646e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
865ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
866ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get all items that can be associated directly or indirectly with the keyCode
867ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        ArrayList<MenuItemImpl> items = mTempShortcutItemList;
868ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        items.clear();
869ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        findItemsWithShortcutForKey(items, keyCode, event);
870ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
871ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (items.isEmpty()) {
872ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return null;
873ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
874ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
875ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
876ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
877ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
878ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        event.getKeyData(possibleChars);
879ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
880ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we have only one element, we can safely returns it
881ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = items.size();
882ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (size == 1) {
883ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.get(0);
884ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
885ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
886ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
887ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we found more than one item associated with the key,
888ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // we have to return the exact match
889ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
890ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = items.get(i);
891ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
892ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    item.getNumericShortcut();
893ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((shortcutChar == possibleChars.meta[0] &&
894ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) == 0)
895ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    || (shortcutChar == possibleChars.meta[2] &&
896ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) != 0)
897ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    || (qwerty && shortcutChar == '\b' &&
898ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    keyCode == KeyEvent.KEYCODE_DEL)) {
899ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
900ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
901ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
902ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
903ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
904ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9056e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
906ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performIdentifierAction(int id, int flags) {
907ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose identifier is the id.
908ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return performItemAction(findItem(id), flags);
909ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
910ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
911ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performItemAction(MenuItem item, int flags) {
912ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl itemImpl = (MenuItemImpl) item;
913ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
914ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl == null || !itemImpl.isEnabled()) {
915ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return false;
916ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
917ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
918ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean invoked = itemImpl.invoke();
919ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
92030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        final ActionProvider provider = itemImpl.getSupportActionProvider();
921ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean providerHasSubMenu = provider != null && provider.hasSubMenu();
922ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl.hasCollapsibleActionView()) {
923ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            invoked |= itemImpl.expandActionView();
92420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (invoked) {
92520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                close(true);
92620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
927ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else if (itemImpl.hasSubMenu() || providerHasSubMenu) {
928ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            close(false);
929ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
930ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (!itemImpl.hasSubMenu()) {
931ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemImpl.setSubMenu(new SubMenuBuilder(getContext(), this, itemImpl));
932ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
933ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
934ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final SubMenuBuilder subMenu = (SubMenuBuilder) itemImpl.getSubMenu();
935ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (providerHasSubMenu) {
936ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                provider.onPrepareSubMenu(subMenu);
937ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
938ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            invoked |= dispatchSubMenuSelected(subMenu);
93920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (!invoked) {
94020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                close(true);
94120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
942ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
943ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
944ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                close(true);
945ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
946ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
947ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
948ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return invoked;
949ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
950ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
951ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
952ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Closes the visible menu.
953ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
95420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param allMenusAreClosing Whether the menus are completely closing (true), or whether there
95520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                           is another menu coming in this menu's place (false). For example,
95620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                           if the menu is closing because a sub menu is about to be shown,
95720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                           <var>allMenusAreClosing</var> is false.
958ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
959ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    final void close(boolean allMenusAreClosing) {
96020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mIsClosing) {
96120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
96220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
963ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
964ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = true;
965ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
966ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
967ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
968ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
969ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
970ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.onCloseMenu(this, allMenusAreClosing);
971ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
972ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
973ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = false;
974ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
975ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9766e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
977ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void close() {
978ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        close(true);
979ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
980ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
981ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
982ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called when an item is added or removed.
983ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
98420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param structureChanged true if the menu structure changed, false if only item properties
98520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         changed. (Visibility is a structural property since it affects
98620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         layout.)
987ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
988ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemsChanged(boolean structureChanged) {
989ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mPreventDispatchingItemsChanged) {
990ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (structureChanged) {
991ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mIsVisibleItemsStale = true;
992ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mIsActionItemsStale = true;
993ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
994ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
995ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            dispatchPresenterUpdate(structureChanged);
996ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
997ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = true;
998ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
999ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1000ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1001ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
100220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Stop dispatching item changed events to presenters until {@link
100320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * #startDispatchingItemsChanged()} is called. Useful when many menu operations are going to be
100420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * performed as a batch.
1005ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1006ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void stopDispatchingItemsChanged() {
1007ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mPreventDispatchingItemsChanged) {
1008ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPreventDispatchingItemsChanged = true;
1009ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = false;
1010ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1011ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1012ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1013ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void startDispatchingItemsChanged() {
1014ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
1015ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1016ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mItemsChangedWhileDispatchPrevented) {
1017ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = false;
1018ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
1019ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1020ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1021ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1022ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1023ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by {@link MenuItemImpl} when its visible flag is changed.
102420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1025ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param item The item that has gone through a visibility change.
1026b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
1027ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemVisibleChanged(MenuItemImpl item) {
1028ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of items being changed
1029ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
1030ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
1031ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1032ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1033ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1034ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by {@link MenuItemImpl} when its action request status is changed.
103520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1036ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param item The item that has gone through a change in action request status.
1037ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1038ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemActionRequestChanged(MenuItemImpl item) {
1039ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of items being changed
1040ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1041ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
1042ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1043ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1044ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    ArrayList<MenuItemImpl> getVisibleItems() {
104520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (!mIsVisibleItemsStale) {
104620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return mVisibleItems;
104720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
1048ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1049ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Refresh the visible items
1050ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems.clear();
1051ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1052ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemsSize = mItems.size();
1053ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl item;
1054ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemsSize; i++) {
1055ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item = mItems.get(i);
105620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (item.isVisible()) {
105720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mVisibleItems.add(item);
105820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
1059ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1060ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1061ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = false;
1062ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1063ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1064ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mVisibleItems;
1065ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1066ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1067ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1068ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This method determines which menu items get to be 'action items' that will appear
1069ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in an action bar and which items should be 'overflow items' in a secondary menu.
1070ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * The rules are as follows:
1071ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1072ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>Items are considered for inclusion in the order specified within the menu.
1073ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * There is a limit of mMaxActionItems as a total count, optionally including the overflow
1074ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * menu button itself. This is a soft limit; if an item shares a group ID with an item
1075ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * previously included as an action item, the new item will stay with its group and become
1076ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * an action item itself even if it breaks the max item count limit. This is done to
1077ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit the conceptual complexity of the items presented within an action bar. Only a few
1078ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * unrelated concepts should be presented to the user in this space, and groups are treated
1079ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * as a single concept.
1080ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1081ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This
1082ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit may be broken by a single item that exceeds the remaining space, but no further
1083ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * items may be added. If an item that is part of a group cannot fit within the remaining
1084ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * measured width, the entire group will be demoted to overflow. This is done to ensure room
1085ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * for navigation and other affordances in the action bar as well as reduce general UI clutter.
1086ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1087ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>The space freed by demoting a full group cannot be consumed by future menu items.
1088ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Once items begin to overflow, all future items become overflow items as well. This is
1089ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to avoid inadvertent reordering that may break the app's intended design.
1090ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1091ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void flagActionItems() {
1092ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mIsActionItemsStale) {
1093ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
1094ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1095ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1096ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Presenters flag action items as needed.
1097ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean flagged = false;
1098ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1099ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
1103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                flagged |= presenter.flagActionItems();
1104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (flagged) {
1108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
1111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int itemsSize = visibleItems.size();
1112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            for (int i = 0; i < itemsSize; i++) {
1113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItemImpl item = visibleItems.get(i);
1114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (item.isActionButton()) {
1115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mActionItems.add(item);
1116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                } else {
1117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mNonActionItems.add(item);
1118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
1119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1121ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Nobody flagged anything, everything is a non-action item.
1122ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // (This happens during a first pass with no action-item presenters.)
1123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1125ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.addAll(getVisibleItems());
1126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1127ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = false;
1128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    ArrayList<MenuItemImpl> getActionItems() {
1131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1132ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mActionItems;
1133ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    ArrayList<MenuItemImpl> getNonActionItems() {
1136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mNonActionItems;
1138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1139ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearHeader() {
1141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderIcon = null;
1142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderTitle = null;
1143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderView = null;
1144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
114920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final Drawable icon, final View view) {
1150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Resources r = getResources();
1151ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (view != null) {
1153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = view;
1154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using a custom view, then the title and icon aren't used
1156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderTitle = null;
1157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderIcon = null;
1158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (titleRes > 0) {
1160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = r.getText(titleRes);
1161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (title != null) {
1162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = title;
1163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (iconRes > 0) {
1166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderIcon = r.getDrawable(iconRes);
1167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (icon != null) {
1168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderIcon = icon;
1169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using the title or icon, then a custom view isn't used
1172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = null;
1173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of change
1176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
118020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's title. This replaces the header view. Called by the builder-style methods
118120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * of subclasses.
1182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param title The new title.
1184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
1187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, title, 0, null, null);
1188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
119220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's title. This replaces the header view. Called by the builder-style methods
119320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * of subclasses.
1194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param titleRes The new title (as a resource ID).
1196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(int titleRes) {
1199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(titleRes, null, 0, null, null);
1200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
120420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's icon. This replaces the header view. Called by the builder-style methods of
120520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * subclasses.
1206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param icon The new icon.
1208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(Drawable icon) {
1211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, icon, null);
1212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
121620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's icon. This replaces the header view. Called by the builder-style methods of
121720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * subclasses.
1218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param iconRes The new icon (as a resource ID).
1220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(int iconRes) {
1223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, iconRes, null, null);
1224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
122820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's view. This replaces the title and icon. Called by the builder-style methods
122920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * of subclasses.
1230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param view The new view.
1232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderViewInt(View view) {
1235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, null, view);
1236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public CharSequence getHeaderTitle() {
1240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderTitle;
1241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Drawable getHeaderIcon() {
1244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderIcon;
1245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public View getHeaderView() {
1248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderView;
1249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Gets the root menu (if this is a submenu, find its root menu).
125320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return The root menu.
1255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder getRootMenu() {
1257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
126120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the current menu info that is set on all items added to this menu (until this is called
126220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * again with different menu info, in which case that one will be added to all subsequent item
126320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * additions).
1264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param menuInfo The extra menu information to add.
1266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCurrentMenuInfo(ContextMenu.ContextMenuInfo menuInfo) {
1268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCurrentMenuInfo = menuInfo;
1269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setOptionalIconsVisible(boolean visible) {
1272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mOptionalIconsVisible = visible;
1273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean getOptionalIconsVisible() {
1276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mOptionalIconsVisible;
1277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean expandItemActionView(MenuItemImpl item) {
128020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty()) {
128120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return false;
128220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
1283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean expanded = false;
1285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
1287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if ((expanded = presenter.expandItemActionView(this, item))) {
1292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                break;
1293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
1296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expanded) {
1298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedItem = item;
1299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1300ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return expanded;
1301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean collapseItemActionView(MenuItemImpl item) {
130420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty() || mExpandedItem != item) {
130520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return false;
130620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
1307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean collapsed = false;
1309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
1311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if ((collapsed = presenter.collapseItemActionView(this, item))) {
1316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                break;
1317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
1320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (collapsed) {
1322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedItem = null;
1323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return collapsed;
1325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItemImpl getExpandedItem() {
1328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mExpandedItem;
1329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1330bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell}
1331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1332