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