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.
3689208232f3b5d1451408d787872504a190bc7ee0Chris Banes *
3789208232f3b5d1451408d787872504a190bc7ee0Chris Banes * @hide
38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
3930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellpublic class MenuBuilder implements SupportMenu {
4020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
41ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String TAG = "MenuBuilder";
42ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
43ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String PRESENTER_KEY = "android:menu:presenters";
44ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
45ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview";
46ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    private static final int[] sCategoryToOrder = new int[]{
48ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            1, /* No category */
49ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            4, /* CONTAINER */
50ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            5, /* SYSTEM */
51ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            3, /* SECONDARY */
52ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            2, /* ALTERNATIVE */
53ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            0, /* SELECTED_ALTERNATIVE */
54ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    };
55ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
56ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Context mContext;
5720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private final Resources mResources;
59ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
60ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
6120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode() instead of accessing
6220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * this directly.
63ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
64ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mQwertyMode;
65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
66ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
6720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether the shortcuts should be visible on menus. Use isShortcutsVisible() instead of
6820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * accessing this directly.
69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mShortcutsVisible;
71ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
72ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
7320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Callback that will receive the various menu-related events generated by this class. Use
7420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * getCallback to get a reference to the callback.
75ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
76ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private Callback mCallback;
77ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
7920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Contains all of the items for this menu
8020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
81ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mItems;
82ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
8320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
8420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Contains only the items that are currently visible.  This will be created/refreshed from
8520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * {@link #getVisibleItems()}
8620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
87ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mVisibleItems;
8820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
89ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
90ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Whether or not the items (or any one item's shown state) has changed since it was last
91ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * fetched from {@link #getVisibleItems()}
92ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
93ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsVisibleItemsStale;
94ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
95ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
96ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Contains only the items that should appear in the Action Bar, if present.
97ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
98ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mActionItems;
9920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Contains items that should NOT appear in the Action Bar, if present.
102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mNonActionItems;
104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
10620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Whether or not the items (or any one item's action state) has changed since it was last
10720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * fetched.
108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsActionItemsStale;
110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Default value for how added items should show in the action list.
113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
11430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    private int mDefaultShowAsAction = SupportMenuItem.SHOW_AS_ACTION_NEVER;
115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
11720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Current use case is Context Menus: As Views populate the context menu, each one has extra
11820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * information that should be passed along.  This is the current menu info that should be set on
11920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * all items added to this menu.
120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
121ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ContextMenu.ContextMenuInfo mCurrentMenuInfo;
122ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
12320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
12420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header title for menu types that have a header (context and submenus)
12520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    CharSequence mHeaderTitle;
12720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
12820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
12920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header icon for menu types that have a header and support icons (context)
13020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Drawable mHeaderIcon;
13220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
13320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns    /**
13420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Header custom view for menu types that have a header and support custom views (context)
13520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     */
136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    View mHeaderView;
137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
13920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Prevents onItemsChanged from doing its junk, useful for batching commands that may
14020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * individually call onItemsChanged.
141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mPreventDispatchingItemsChanged = false;
14320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mItemsChangedWhileDispatchPrevented = false;
145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mOptionalIconsVisible = false;
147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mIsClosing = false;
149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ArrayList<MenuItemImpl> mTempShortcutItemList = new ArrayList<MenuItemImpl>();
151ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private CopyOnWriteArrayList<WeakReference<MenuPresenter>> mPresenters =
153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            new CopyOnWriteArrayList<WeakReference<MenuPresenter>>();
154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Currently expanded menu item; must be collapsed when we clear.
157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuItemImpl mExpandedItem;
159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by menu to notify of close and selection changes.
16289208232f3b5d1451408d787872504a190bc7ee0Chris Banes     * @hide
163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public interface Callback {
16520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        /**
167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * Called when a menu item is selected.
16820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *
169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param menu The menu that is the parent of the item
170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param item The menu item that is selected
171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @return whether the menu item selection was handled
172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         */
173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        /**
176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * Called when the mode of the menu changes (for example, from icon to expanded).
177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         *
178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         * @param menu the menu that has changed modes
179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani         */
180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public void onMenuModeChange(MenuBuilder menu);
181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by menu items to execute their associated action
18589208232f3b5d1451408d787872504a190bc7ee0Chris Banes     * @hide
186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public interface ItemInvoker {
18820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public boolean invokeItem(MenuItemImpl item);
190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder(Context context) {
193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mContext = context;
194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mResources = context.getResources();
195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems = new ArrayList<MenuItemImpl>();
197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems = new ArrayList<MenuItemImpl>();
199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mActionItems = new ArrayList<MenuItemImpl>();
202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mNonActionItems = new ArrayList<MenuItemImpl>();
203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(true);
206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mDefaultShowAsAction = defaultShowAsAction;
210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
21420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Add a presenter to this menu. This will only hold a WeakReference; you do not need to
21520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * explicitly remove a presenter, but you can using {@link #removeMenuPresenter(MenuPresenter)}.
216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to add
218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void addMenuPresenter(MenuPresenter presenter) {
220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPresenters.add(new WeakReference<MenuPresenter>(presenter));
221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        presenter.initForMenu(mContext, this);
222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
22620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Remove a presenter from this menu. That presenter will no longer receive notifications of
22720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * updates to this menu's data.
228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param presenter The presenter to remove
230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeMenuPresenter(MenuPresenter presenter) {
232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter item = ref.get();
234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item == null || item == presenter) {
235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchPresenterUpdate(boolean cleared) {
24120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty()) {
24220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
24320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.updateMenuView(cleared);
252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) {
25820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty()) {
25920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return false;
26020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean result = false;
263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (!result) {
269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                result = presenter.onSubMenuSelected(subMenu);
270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return result;
273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchSaveInstanceState(Bundle outState) {
27620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty()) {
27720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
27820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    final Parcelable state = presenter.onSaveInstanceState();
290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (state != null) {
291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenterStates.put(id, state);
292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
300ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void dispatchRestoreInstanceState(Bundle state) {
301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
30320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (presenterStates == null || mPresenters.isEmpty()) {
30420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
30520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int id = presenter.getId();
313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (id > 0) {
314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    Parcelable parcel = presenterStates.get(id);
315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (parcel != null) {
316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        presenter.onRestoreInstanceState(parcel);
317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void savePresenterStates(Bundle outState) {
324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchSaveInstanceState(outState);
325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restorePresenterStates(Bundle state) {
328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dispatchRestoreInstanceState(state);
329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void saveActionViewStates(Bundle outStates) {
332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = null;
333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
33730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (viewStates == null) {
340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    viewStates = new SparseArray<Parcelable>();
341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.saveHierarchyState(viewStates);
34330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                if (MenuItemCompat.isActionViewExpanded(item)) {
344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId());
345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.saveActionViewStates(outStates);
350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (viewStates != null) {
354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates);
355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void restoreActionViewStates(Bundle states) {
359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (states == null) {
360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        SparseArray<Parcelable> viewStates = states.getSparseParcelableArray(
364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                getActionViewStatesKey());
365ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemCount = size();
367ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemCount; i++) {
368ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = getItem(i);
36930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            final View v = MenuItemCompat.getActionView(item);
370ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (v != null && v.getId() != View.NO_ID) {
371ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                v.restoreHierarchyState(viewStates);
372ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
373ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
374ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
375ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                subMenu.restoreActionViewStates(states);
376ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
377ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
378ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
379ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID);
380ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expandedId > 0) {
381ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItem itemToExpand = findItem(expandedId);
382ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (itemToExpand != null) {
38330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                MenuItemCompat.expandActionView(itemToExpand);
384ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
385ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
386ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
387ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
388ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected String getActionViewStatesKey() {
389ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return ACTION_VIEW_STATES_KEY;
390ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
391ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
392ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCallback(Callback cb) {
393ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCallback = cb;
394ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
395ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
396ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
397ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Adds an item to the menu.  The other add methods funnel to this.
398ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
399ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
400ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int ordering = getOrdering(categoryOrder);
401ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
402ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder,
403ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                ordering, title, mDefaultShowAsAction);
404ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
405ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCurrentMenuInfo != null) {
406ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Pass along the current menu info
407ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item.setMenuInfo(mCurrentMenuInfo);
408ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
409ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
410ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.add(findInsertIndex(mItems, ordering), item);
411ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
412ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
413ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return item;
414ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
415ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4166e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
417ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(CharSequence title) {
418ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, title);
419ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
420ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4216e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
422ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int titleRes) {
423ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(0, 0, 0, mResources.getString(titleRes));
424ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
425ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4266e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
427ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
428ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, title);
429ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
430ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4316e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
432ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem add(int group, int id, int categoryOrder, int title) {
433ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addInternal(group, id, categoryOrder, mResources.getString(title));
434ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
435ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4366e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
437ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(CharSequence title) {
438ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, title);
439ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
440ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4416e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
442ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int titleRes) {
443ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
444ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
445ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4466e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
447ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
448ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
449ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
450ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        item.setSubMenu(subMenu);
451ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
452ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return subMenu;
453ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
454ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4556e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
456ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
457ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
458ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
459ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4606e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
461ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
46220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
463ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        PackageManager pm = mContext.getPackageManager();
464ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final List<ResolveInfo> lri =
465ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
466ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = lri != null ? lri.size() : 0;
467ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
468ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
469ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            removeGroup(group);
470ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
471ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
47220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        for (int i = 0; i < N; i++) {
473ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final ResolveInfo ri = lri.get(i);
474ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            Intent rintent = new Intent(
475ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
476ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            rintent.setComponent(new ComponentName(
477ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.applicationInfo.packageName,
478ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    ri.activityInfo.name));
479ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
480ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIcon(ri.loadIcon(pm))
481ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    .setIntent(rintent);
482ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (outSpecificItems != null && ri.specificIndex >= 0) {
483ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                outSpecificItems[ri.specificIndex] = item;
484ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
485ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
486ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
487ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return N;
488ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
489ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4906e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
491ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItem(int id) {
492ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(findItemIndex(id), true);
493ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
494ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
4956e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
496ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeGroup(int group) {
497ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int i = findGroupIndex(group);
498ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
499ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (i >= 0) {
500ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int maxRemovable = mItems.size() - i;
501ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            int numRemoved = 0;
502ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
503ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Don't force update for each one, this method will do it at the end
504ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                removeItemAtInt(i, false);
505ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
506ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
507ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Notify menu views
508ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
509ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
510ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
511ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
512ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
51320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Remove the item at the given index and optionally forces menu views to update.
514ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
51520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param index                     The index of the item to be removed. If this index is
51620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                                  invalid an exception is thrown.
51720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param updateChildrenOnMenuViews Whether to force update on menu views. Please make sure you
51820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                                  eventually call this after your batch of removals.
519ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
520ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
52120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if ((index < 0) || (index >= mItems.size())) {
52220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
52320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
524ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
525ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.remove(index);
526ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
52720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (updateChildrenOnMenuViews) {
52820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            onItemsChanged(true);
52920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
530ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
531ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
532ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void removeItemAt(int index) {
533ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        removeItemAtInt(index, true);
534ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
535ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
536ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearAll() {
537ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = true;
538ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clear();
539ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        clearHeader();
540ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
541ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItemsChangedWhileDispatchPrevented = false;
542ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
543ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
544ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5456e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
546ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clear() {
547ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mExpandedItem != null) {
548ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            collapseItemActionView(mExpandedItem);
549ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
550ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItems.clear();
551ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
552ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
553ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
554ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
555ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setExclusiveItemChecked(MenuItem item) {
556ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int group = item.getGroupId();
557ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
558ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
559ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
560ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl curItem = mItems.get(i);
561ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (curItem.getGroupId() == group) {
56220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (!curItem.isExclusiveCheckable()) {
56320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    continue;
56420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
56520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (!curItem.isCheckable()) {
56620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    continue;
56720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
568ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
569ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Check the item meant to be checked, uncheck the others (that are in the group)
570ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                curItem.setCheckedInt(curItem == item);
571ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
572ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
573ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
574ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5756e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
576ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
577ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
578ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
579ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
580ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
581ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
582ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setExclusiveCheckable(exclusive);
583ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setCheckable(checkable);
584ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
585ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
586ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
587ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
5886e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
589ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupVisible(int group, boolean visible) {
590ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
591ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
59220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        // We handle the notification of items being changed ourselves, so we use setVisibleInt
59320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        // rather than setVisible and at the end notify of items being changed
594ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
595ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean changedAtLeastOneItem = false;
596ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
597ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
598ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
59920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (item.setVisibleInt(visible)) {
60020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    changedAtLeastOneItem = true;
60120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
602ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
603ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
604ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
60520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (changedAtLeastOneItem) {
60620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            onItemsChanged(true);
60720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
608ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
609ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6106e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
611ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setGroupEnabled(int group, boolean enabled) {
612ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
613ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
614ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
615ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
616ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
617ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                item.setEnabled(enabled);
618ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
619ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
620ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
621ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6226e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
623ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean hasVisibleItems() {
624ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
625bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
626ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
627ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
628ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.isVisible()) {
629ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return true;
630ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
631ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
632bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
633ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
634ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
635bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
6366e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
637ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem findItem(int id) {
638ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
639ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
640ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
641ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
642ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
643ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (item.hasSubMenu()) {
644ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItem possibleItem = item.getSubMenu().findItem(id);
645bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
646ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (possibleItem != null) {
647ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    return possibleItem;
648ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
649ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
650ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
651bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
652ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
653ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
654bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
655ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findItemIndex(int id) {
656ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
657bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
658ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
659ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
660ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getItemId() == id) {
661ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
662ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
663ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
664bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
665ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
666ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
667bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
668ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group) {
669ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findGroupIndex(group, 0);
670ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
671bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
672ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int findGroupIndex(int group, int start) {
673ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = size();
674bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
675ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (start < 0) {
676ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            start = 0;
677ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
678ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
679ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = start; i < size; i++) {
680ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = mItems.get(i);
681ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
682ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getGroupId() == group) {
683ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i;
684ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
685ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
686ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
687ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return -1;
688ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
689ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6906e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
691ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int size() {
692ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.size();
693ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
694ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6956e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
696ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItem getItem(int index) {
697ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItems.get(index);
698ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
699ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7006e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
701ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutKey(int keyCode, KeyEvent event) {
702ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return findItemWithShortcutForKey(keyCode, event) != null;
703ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
704ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
7056e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
706ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setQwertyMode(boolean isQwerty) {
707ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mQwertyMode = isQwerty;
708ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
709ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
710ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
711ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
712ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
71320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Returns the ordering across all items. This will grab the category from the upper bits, find
71420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * out how to order the category with respect to other categories, and combine it with the lower
71520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * bits.
716ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
71720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param categoryOrder The category order for a particular item (if it has not been or/add with
71820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                      a category, the default category is assumed).
71920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return An ordering integer that can be used to order this item across all the items (even
72020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *         from other categories).
721ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
722ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int getOrdering(int categoryOrder) {
723ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
724ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
725ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (index < 0 || index >= sCategoryToOrder.length) {
726ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            throw new IllegalArgumentException("order does not contain a valid category.");
727ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
728ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
729ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
730ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
731b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
732b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
733ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return whether the menu shortcuts are in qwerty mode or not
734b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
735ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean isQwertyMode() {
736ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mQwertyMode;
737ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
738b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns
739b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns    /**
74020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets whether the shortcuts should be visible on menus.  Devices without hardware key input
74120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * will never make shortcuts visible even if this method is passed 'true'.
742b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     *
74320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param shortcutsVisible Whether shortcuts should be visible (if true and a menu item does not
74420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         have a shortcut defined, that item will still NOT show a shortcut)
745ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
746ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setShortcutsVisible(boolean shortcutsVisible) {
74720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mShortcutsVisible == shortcutsVisible) {
74820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
74920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
750ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
751ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setShortcutsVisibleInner(shortcutsVisible);
752ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
753ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
754ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
755ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setShortcutsVisibleInner(boolean shortcutsVisible) {
756ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mShortcutsVisible = shortcutsVisible
757ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS
75807a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes                && mResources.getBoolean(R.bool.abc_config_showMenuShortcutsWhenKeyboardPresent);
759ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
760ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
761ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
762ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return Whether shortcuts should be visible on menus.
763ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
764ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShortcutsVisible() {
765ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mShortcutsVisible;
766ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
767ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
768ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    Resources getResources() {
769ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mResources;
770ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
771ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
772ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Context getContext() {
773ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mContext;
774ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
775ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
776ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) {
777ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mCallback != null && mCallback.onMenuItemSelected(menu, item);
778ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
779ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
780ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
781ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Dispatch a mode change event to this menu's callback.
782ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
783ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void changeMenuMode() {
784ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mCallback != null) {
785ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mCallback.onMenuModeChange(this);
786ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
787ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
788ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
789ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
790ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = items.size() - 1; i >= 0; i--) {
791ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = items.get(i);
792ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.getOrdering() <= ordering) {
793ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return i + 1;
794ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
795ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
796ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
797ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return 0;
798ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
799ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
8006e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
801ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
802ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
803ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
804ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean handled = false;
805ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
806ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (item != null) {
807ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            handled = performItemAction(item, flags);
808ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
809ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
810ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
811ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            close(true);
812ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
813ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
814ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return handled;
815ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
816ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
817ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
818ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This function will return all the menu and sub-menu items that can
819ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * be directly (the shortcut directly corresponds) and indirectly
820ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * (the ALT-enabled char corresponds to the shortcut) associated
821ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * with the keyCode.
822ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8236e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
824ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
825ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
826ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
827ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
828ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
829ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
830ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // The delete key is not mapped to '\b' so we treat it specially
831ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
832ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
833ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
834ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
835ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose shortcut is this key.
836ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int N = mItems.size();
837ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < N; i++) {
838ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuItemImpl item = mItems.get(i);
839ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (item.hasSubMenu()) {
84020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                ((MenuBuilder) item.getSubMenu())
84120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        .findItemsWithShortcutForKey(items, keyCode, event);
842ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
84320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final char shortcutChar = qwerty ? item.getAlphabeticShortcut()
84420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    : item.getNumericShortcut();
845ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
846ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (shortcutChar != 0) &&
847ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (shortcutChar == possibleChars.meta[0]
848ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                            || shortcutChar == possibleChars.meta[2]
849ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                            || (qwerty && shortcutChar == '\b' &&
850ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                            keyCode == KeyEvent.KEYCODE_DEL)) &&
851ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    item.isEnabled()) {
852ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                items.add(item);
853ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
854ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
855ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
856ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
857ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /*
858ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * We want to return the menu item associated with the key, but if there is no
859ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * ambiguity (i.e. there is only one menu item corresponding to the key) we want
860ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to return it even if it's not an exact match; this allow the user to
861ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * _not_ use the ALT key for example, making the use of shortcuts slightly more
862ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
863ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
864ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
865ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * On the other hand, if two (or more) shortcuts corresponds to the same key,
866ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * we have to only return the exact match.
867ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
8686e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @SuppressWarnings("deprecation")
869ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
870ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get all items that can be associated directly or indirectly with the keyCode
871ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        ArrayList<MenuItemImpl> items = mTempShortcutItemList;
872ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        items.clear();
873ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        findItemsWithShortcutForKey(items, keyCode, event);
874ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
875ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (items.isEmpty()) {
876ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return null;
877ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
878ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
879ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int metaState = event.getMetaState();
880ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
881ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Get the chars associated with the keyCode (i.e using any chording combo)
882ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        event.getKeyData(possibleChars);
883ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
884ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we have only one element, we can safely returns it
885ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int size = items.size();
886ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (size == 1) {
887ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.get(0);
888ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
889ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
890ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean qwerty = isQwertyMode();
891ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // If we found more than one item associated with the key,
892ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // we have to return the exact match
893ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < size; i++) {
894ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl item = items.get(i);
895ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
896ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    item.getNumericShortcut();
897ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((shortcutChar == possibleChars.meta[0] &&
898ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) == 0)
899ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    || (shortcutChar == possibleChars.meta[2] &&
900ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    (metaState & KeyEvent.META_ALT_ON) != 0)
901ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    || (qwerty && shortcutChar == '\b' &&
902ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    keyCode == KeyEvent.KEYCODE_DEL)) {
903ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return item;
904ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
905ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
906ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
907ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
908ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9096e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
910ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performIdentifierAction(int id, int flags) {
911ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Look for an item whose identifier is the id.
912ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return performItemAction(findItem(id), flags);
913ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
914ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
915ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean performItemAction(MenuItem item, int flags) {
916ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl itemImpl = (MenuItemImpl) item;
917ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
918ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl == null || !itemImpl.isEnabled()) {
919ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return false;
920ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
921ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
922ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean invoked = itemImpl.invoke();
923ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
92430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        final ActionProvider provider = itemImpl.getSupportActionProvider();
925ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean providerHasSubMenu = provider != null && provider.hasSubMenu();
926ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (itemImpl.hasCollapsibleActionView()) {
927ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            invoked |= itemImpl.expandActionView();
92820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (invoked) {
92920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                close(true);
93020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
931ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else if (itemImpl.hasSubMenu() || providerHasSubMenu) {
932ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            close(false);
933ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
934ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (!itemImpl.hasSubMenu()) {
935ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemImpl.setSubMenu(new SubMenuBuilder(getContext(), this, itemImpl));
936ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
937ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
938ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final SubMenuBuilder subMenu = (SubMenuBuilder) itemImpl.getSubMenu();
939ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (providerHasSubMenu) {
940ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                provider.onPrepareSubMenu(subMenu);
941ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
942ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            invoked |= dispatchSubMenuSelected(subMenu);
94320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (!invoked) {
94420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                close(true);
94520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
946ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
947ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
948ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                close(true);
949ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
950ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
951ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
952ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return invoked;
953ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
954ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
955ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
956ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Closes the visible menu.
957ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
95820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param allMenusAreClosing Whether the menus are completely closing (true), or whether there
95920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                           is another menu coming in this menu's place (false). For example,
96020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                           if the menu is closing because a sub menu is about to be shown,
96120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                           <var>allMenusAreClosing</var> is false.
962ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
963ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    final void close(boolean allMenusAreClosing) {
96420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mIsClosing) {
96520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
96620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
967ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
968ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = true;
969ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
970ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
971ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
972ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
973ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
974ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                presenter.onCloseMenu(this, allMenusAreClosing);
975ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
976ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
977ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsClosing = false;
978ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
979ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9806e6abe6eb358db4c3932752249c8ac61dd3dab21Jeff Brown    @Override
981ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void close() {
982ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        close(true);
983ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
984ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
985ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
986ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called when an item is added or removed.
987ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
98820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param structureChanged true if the menu structure changed, false if only item properties
98920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         changed. (Visibility is a structural property since it affects
99020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                         layout.)
991ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
992ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemsChanged(boolean structureChanged) {
993ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mPreventDispatchingItemsChanged) {
994ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (structureChanged) {
995ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mIsVisibleItemsStale = true;
996ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mIsActionItemsStale = true;
997ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
998ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
999ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            dispatchPresenterUpdate(structureChanged);
1000ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1001ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = true;
1002ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1003ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1004ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1005ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
100620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Stop dispatching item changed events to presenters until {@link
100720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * #startDispatchingItemsChanged()} is called. Useful when many menu operations are going to be
100820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * performed as a batch.
1009ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1010ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void stopDispatchingItemsChanged() {
1011ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mPreventDispatchingItemsChanged) {
1012ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPreventDispatchingItemsChanged = true;
1013ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = false;
1014ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1015ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1016ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1017ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void startDispatchingItemsChanged() {
1018ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPreventDispatchingItemsChanged = false;
1019ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1020ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mItemsChangedWhileDispatchPrevented) {
1021ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemsChangedWhileDispatchPrevented = false;
1022ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            onItemsChanged(true);
1023ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1024ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1025ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1026ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1027ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by {@link MenuItemImpl} when its visible flag is changed.
102820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1029ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param item The item that has gone through a visibility change.
1030b17b7b75ce2989f50a12ef00f198276e30b9c780Trevor Johns     */
1031ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemVisibleChanged(MenuItemImpl item) {
1032ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of items being changed
1033ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = true;
1034ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
1035ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1036ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1037ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1038ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Called by {@link MenuItemImpl} when its action request status is changed.
103920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1040ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param item The item that has gone through a change in action request status.
1041ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1042ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void onItemActionRequestChanged(MenuItemImpl item) {
1043ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of items being changed
1044ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1045ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(true);
1046ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1047ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1048ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    ArrayList<MenuItemImpl> getVisibleItems() {
104920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (!mIsVisibleItemsStale) {
105020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return mVisibleItems;
105120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
1052ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1053ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Refresh the visible items
1054ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mVisibleItems.clear();
1055ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1056ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int itemsSize = mItems.size();
1057ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuItemImpl item;
1058ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < itemsSize; i++) {
1059ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            item = mItems.get(i);
106020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (item.isVisible()) {
106120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mVisibleItems.add(item);
106220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
1063ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1064ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1065ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsVisibleItemsStale = false;
1066ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = true;
1067ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1068ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mVisibleItems;
1069ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1070ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1071ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1072ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * This method determines which menu items get to be 'action items' that will appear
1073ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * in an action bar and which items should be 'overflow items' in a secondary menu.
1074ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * The rules are as follows:
1075ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1076ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>Items are considered for inclusion in the order specified within the menu.
1077ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * There is a limit of mMaxActionItems as a total count, optionally including the overflow
1078ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * menu button itself. This is a soft limit; if an item shares a group ID with an item
1079ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * previously included as an action item, the new item will stay with its group and become
1080ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * an action item itself even if it breaks the max item count limit. This is done to
1081ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit the conceptual complexity of the items presented within an action bar. Only a few
1082ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * unrelated concepts should be presented to the user in this space, and groups are treated
1083ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * as a single concept.
1084ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1085ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This
1086ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * limit may be broken by a single item that exceeds the remaining space, but no further
1087ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * items may be added. If an item that is part of a group cannot fit within the remaining
1088ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * measured width, the entire group will be demoted to overflow. This is done to ensure room
1089ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * for navigation and other affordances in the action bar as well as reduce general UI clutter.
1090ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1091ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * <p>The space freed by demoting a full group cannot be consumed by future menu items.
1092ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Once items begin to overflow, all future items become overflow items as well. This is
1093ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * to avoid inadvertent reordering that may break the app's intended design.
1094ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1095ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void flagActionItems() {
1096ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!mIsActionItemsStale) {
1097ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return;
1098ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1099ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Presenters flag action items as needed.
1101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean flagged = false;
1102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else {
1107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                flagged |= presenter.flagActionItems();
1108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (flagged) {
1112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
1115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int itemsSize = visibleItems.size();
1116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            for (int i = 0; i < itemsSize; i++) {
1117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItemImpl item = visibleItems.get(i);
1118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (item.isActionButton()) {
1119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mActionItems.add(item);
1120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                } else {
1121ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mNonActionItems.add(item);
1122ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
1123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1125ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Nobody flagged anything, everything is a non-action item.
1126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // (This happens during a first pass with no action-item presenters.)
1127ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mActionItems.clear();
1128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.clear();
1129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mNonActionItems.addAll(getVisibleItems());
1130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIsActionItemsStale = false;
1132ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1133ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    ArrayList<MenuItemImpl> getActionItems() {
1135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mActionItems;
1137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1139ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    ArrayList<MenuItemImpl> getNonActionItems() {
1140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        flagActionItems();
1141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mNonActionItems;
1142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void clearHeader() {
1145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderIcon = null;
1146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderTitle = null;
1147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mHeaderView = null;
1148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1151ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
115320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final Drawable icon, final View view) {
1154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Resources r = getResources();
1155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (view != null) {
1157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = view;
1158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using a custom view, then the title and icon aren't used
1160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderTitle = null;
1161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderIcon = null;
1162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
1163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (titleRes > 0) {
1164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = r.getText(titleRes);
1165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (title != null) {
1166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderTitle = title;
1167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (iconRes > 0) {
1170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderIcon = r.getDrawable(iconRes);
1171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (icon != null) {
1172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mHeaderIcon = icon;
1173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // If using the title or icon, then a custom view isn't used
1176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mHeaderView = null;
1177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Notify of change
1180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        onItemsChanged(false);
1181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
118420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's title. This replaces the header view. Called by the builder-style methods
118520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * of subclasses.
1186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param title The new title.
1188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
1191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, title, 0, null, null);
1192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
119620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's title. This replaces the header view. Called by the builder-style methods
119720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * of subclasses.
1198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param titleRes The new title (as a resource ID).
1200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderTitleInt(int titleRes) {
1203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(titleRes, null, 0, null, null);
1204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
120820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's icon. This replaces the header view. Called by the builder-style methods of
120920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * subclasses.
1210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param icon The new icon.
1212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(Drawable icon) {
1215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, icon, null);
1216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
122020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's icon. This replaces the header view. Called by the builder-style methods of
122120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * subclasses.
1222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param iconRes The new icon (as a resource ID).
1224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderIconInt(int iconRes) {
1227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, iconRes, null, null);
1228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
123220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the header's view. This replaces the title and icon. Called by the builder-style methods
123320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * of subclasses.
1234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param view The new view.
1236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return This MenuBuilder so additional setters can be called.
1237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected MenuBuilder setHeaderViewInt(View view) {
1239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setHeaderInternal(0, null, 0, null, view);
1240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public CharSequence getHeaderTitle() {
1244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderTitle;
1245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Drawable getHeaderIcon() {
1248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderIcon;
1249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public View getHeaderView() {
1252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mHeaderView;
1253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
1256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * Gets the root menu (if this is a submenu, find its root menu).
125720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *
1258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @return The root menu.
1259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuBuilder getRootMenu() {
1261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return this;
1262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    /**
126520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the current menu info that is set on all items added to this menu (until this is called
126620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * again with different menu info, in which case that one will be added to all subsequent item
126720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * additions).
1268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     *
1269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     * @param menuInfo The extra menu information to add.
1270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani     */
1271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCurrentMenuInfo(ContextMenu.ContextMenuInfo menuInfo) {
1272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mCurrentMenuInfo = menuInfo;
1273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    void setOptionalIconsVisible(boolean visible) {
1276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mOptionalIconsVisible = visible;
1277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean getOptionalIconsVisible() {
1280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mOptionalIconsVisible;
1281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean expandItemActionView(MenuItemImpl item) {
128420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty()) {
128520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return false;
128620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
1287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean expanded = false;
1289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
1291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if ((expanded = presenter.expandItemActionView(this, item))) {
1296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                break;
1297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
1300ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (expanded) {
1302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedItem = item;
1303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return expanded;
1305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean collapseItemActionView(MenuItemImpl item) {
130820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mPresenters.isEmpty() || mExpandedItem != item) {
130920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return false;
131020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
1311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean collapsed = false;
1313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        stopDispatchingItemsChanged();
1315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (WeakReference<MenuPresenter> ref : mPresenters) {
1316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuPresenter presenter = ref.get();
1317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (presenter == null) {
1318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPresenters.remove(ref);
1319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if ((collapsed = presenter.collapseItemActionView(this, item))) {
1320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                break;
1321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
1322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        startDispatchingItemsChanged();
1324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (collapsed) {
1326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedItem = null;
1327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
1328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return collapsed;
1329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItemImpl getExpandedItem() {
1332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mExpandedItem;
1333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
1334bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell}
1335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
1336