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