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