19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.view.menu; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ResolveInfo; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Configuration; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 2811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powellimport android.os.Bundle; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray; 31961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powellimport android.view.ActionProvider; 3236fced9b211255e2137014e21fb3259042d8da85Adam Powellimport android.view.ContextMenu.ContextMenuInfo; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyCharacterMap; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Menu; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MenuItem; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SubMenu; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 43696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport java.util.concurrent.CopyOnWriteArrayList; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Implementation of the {@link android.view.Menu} interface for creating a 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * standard menu UI. 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class MenuBuilder implements Menu { 5089b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell private static final String TAG = "MenuBuilder"; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell private static final String PRESENTER_KEY = "android:menu:presenters"; 53038f1c80af06da55056120e121d43e3ee89ec726Adam Powell private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates"; 54038f1c80af06da55056120e121d43e3ee89ec726Adam Powell private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview"; 5511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] sCategoryToOrder = new int[] { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1, /* No category */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4, /* CONTAINER */ 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5, /* SYSTEM */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3, /* SECONDARY */ 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2, /* ALTERNATIVE */ 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0, /* SELECTED_ALTERNATIVE */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Resources mResources; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode() 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instead of accessing this directly. 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mQwertyMode; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Whether the shortcuts should be visible on menus. Use isShortcutsVisible() 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instead of accessing this directly. 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mShortcutsVisible; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback that will receive the various menu-related events generated by 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this class. Use getCallback to get a reference to the callback. 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Callback mCallback; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Contains all of the items for this menu */ 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<MenuItemImpl> mItems; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Contains only the items that are currently visible. This will be created/refreshed from 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getVisibleItems()} */ 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<MenuItemImpl> mVisibleItems; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Whether or not the items (or any one item's shown state) has changed since it was last 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fetched from {@link #getVisibleItems()} 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsVisibleItemsStale; 9796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell 9896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell /** 9996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Contains only the items that should appear in the Action Bar, if present. 10096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */ 10196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell private ArrayList<MenuItemImpl> mActionItems; 10296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell /** 10396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Contains items that should NOT appear in the Action Bar, if present. 10496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */ 10596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell private ArrayList<MenuItemImpl> mNonActionItems; 106696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 10736fced9b211255e2137014e21fb3259042d8da85Adam Powell /** 10896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Whether or not the items (or any one item's action state) has changed since it was 10996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * last fetched. 11096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */ 11196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell private boolean mIsActionItemsStale; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1144d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell * Default value for how added items should show in the action list. 1154d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell */ 1164d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell private int mDefaultShowAsAction = MenuItem.SHOW_AS_ACTION_NEVER; 1174d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell 1184d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell /** 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Current use case is Context Menus: As Views populate the context menu, each one has 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * extra information that should be passed along. This is the current menu info that 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * should be set on all items added to this menu. 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ContextMenuInfo mCurrentMenuInfo; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Header title for menu types that have a header (context and submenus) */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence mHeaderTitle; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Header icon for menu types that have a header and support icons (context) */ 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Drawable mHeaderIcon; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Header custom view for menu types that have a header and support custom views (context) */ 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View mHeaderView; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Contains the state of the View hierarchy for all menu views when the menu 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * was frozen. 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SparseArray<Parcelable> mFrozenViewStates; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Prevents onItemsChanged from doing its junk, useful for batching commands 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that may individually call onItemsChanged. 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mPreventDispatchingItemsChanged = false; 143696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell private boolean mItemsChangedWhileDispatchPrevented = false; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mOptionalIconsVisible = false; 1462fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell 147696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell private boolean mIsClosing = false; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 149696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell private ArrayList<MenuItemImpl> mTempShortcutItemList = new ArrayList<MenuItemImpl>(); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 151696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell private CopyOnWriteArrayList<WeakReference<MenuPresenter>> mPresenters = 152696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell new CopyOnWriteArrayList<WeakReference<MenuPresenter>>(); 1536b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell 1546b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell /** 1556b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell * Currently expanded menu item; must be collapsed when we clear. 1566b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell */ 1576b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell private MenuItemImpl mExpandedItem; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 160696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Called by menu to notify of close and selection changes. 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface Callback { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called when a menu item is selected. 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param menu The menu that is the parent of the item 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param item The menu item that is selected 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether the menu item selection was handled 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called when the mode of the menu changes (for example, from icon to expanded). 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param menu the menu that has changed modes 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onMenuModeChange(MenuBuilder menu); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called by menu items to execute their associated action 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface ItemInvoker { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean invokeItem(MenuItemImpl item); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuBuilder(Context context) { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResources = context.getResources(); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItems = new ArrayList<MenuItemImpl>(); 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVisibleItems = new ArrayList<MenuItemImpl>(); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsVisibleItemsStale = true; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell mActionItems = new ArrayList<MenuItemImpl>(); 19696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell mNonActionItems = new ArrayList<MenuItemImpl>(); 19796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell mIsActionItemsStale = true; 19896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell 1994aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown setShortcutsVisibleInner(true); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2024d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) { 2034d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell mDefaultShowAsAction = defaultShowAsAction; 2044d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell return this; 2054d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 207696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell /** 208696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Add a presenter to this menu. This will only hold a WeakReference; 209696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * you do not need to explicitly remove a presenter, but you can using 210696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * {@link #removeMenuPresenter(MenuPresenter)}. 211696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * 212696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * @param presenter The presenter to add 213696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell */ 214696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void addMenuPresenter(MenuPresenter presenter) { 215696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenters.add(new WeakReference<MenuPresenter>(presenter)); 216696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell presenter.initForMenu(mContext, this); 217696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mIsActionItemsStale = true; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 219696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 221696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Remove a presenter from this menu. That presenter will no longer 222696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * receive notifications of updates to this menu's data. 223696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * 224696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * @param presenter The presenter to remove 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 226696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void removeMenuPresenter(MenuPresenter presenter) { 227696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 228696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final MenuPresenter item = ref.get(); 229696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (item == null || item == presenter) { 230696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenters.remove(ref); 231696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 235696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell private void dispatchPresenterUpdate(boolean cleared) { 236696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (mPresenters.isEmpty()) return; 237696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 238640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell stopDispatchingItemsChanged(); 239696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 240696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final MenuPresenter presenter = ref.get(); 241696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (presenter == null) { 242696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenters.remove(ref); 243696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } else { 244696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell presenter.updateMenuView(cleared); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 247640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell startDispatchingItemsChanged(); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 250696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) { 251696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (mPresenters.isEmpty()) return false; 252696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 253696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell boolean result = false; 254696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 255696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 256696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final MenuPresenter presenter = ref.get(); 257696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (presenter == null) { 258696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenters.remove(ref); 259696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } else if (!result) { 260696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell result = presenter.onSubMenuSelected(subMenu); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 263696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell return result; 264696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 265696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 26611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell private void dispatchSaveInstanceState(Bundle outState) { 26711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell if (mPresenters.isEmpty()) return; 26811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 26911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>(); 27011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 27111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 27211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell final MenuPresenter presenter = ref.get(); 27311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell if (presenter == null) { 27411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell mPresenters.remove(ref); 27511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } else { 27611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell final int id = presenter.getId(); 27711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell if (id > 0) { 27811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell final Parcelable state = presenter.onSaveInstanceState(); 27911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell if (state != null) { 28011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell presenterStates.put(id, state); 28111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 28211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 28311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 28411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 28511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 28611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates); 28711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 28811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 28911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell private void dispatchRestoreInstanceState(Bundle state) { 29011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY); 29111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 29211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell if (presenterStates == null || mPresenters.isEmpty()) return; 29311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 29411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 29511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell final MenuPresenter presenter = ref.get(); 29611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell if (presenter == null) { 29711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell mPresenters.remove(ref); 29811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } else { 29911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell final int id = presenter.getId(); 30011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell if (id > 0) { 30111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell Parcelable parcel = presenterStates.get(id); 30211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell if (parcel != null) { 30311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell presenter.onRestoreInstanceState(parcel); 30411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 30511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 30611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 30711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 30811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 30911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 31011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell public void savePresenterStates(Bundle outState) { 31111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell dispatchSaveInstanceState(outState); 31211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 31311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 31411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell public void restorePresenterStates(Bundle state) { 31511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell dispatchRestoreInstanceState(state); 31611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell } 31711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell 318038f1c80af06da55056120e121d43e3ee89ec726Adam Powell public void saveActionViewStates(Bundle outStates) { 319038f1c80af06da55056120e121d43e3ee89ec726Adam Powell SparseArray<Parcelable> viewStates = null; 320038f1c80af06da55056120e121d43e3ee89ec726Adam Powell 321038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final int itemCount = size(); 322038f1c80af06da55056120e121d43e3ee89ec726Adam Powell for (int i = 0; i < itemCount; i++) { 323038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final MenuItem item = getItem(i); 324038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final View v = item.getActionView(); 325038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (v != null && v.getId() != View.NO_ID) { 326038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (viewStates == null) { 327038f1c80af06da55056120e121d43e3ee89ec726Adam Powell viewStates = new SparseArray<Parcelable>(); 328038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 329038f1c80af06da55056120e121d43e3ee89ec726Adam Powell v.saveHierarchyState(viewStates); 330038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (item.isActionViewExpanded()) { 331038f1c80af06da55056120e121d43e3ee89ec726Adam Powell outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId()); 332038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 333038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 334038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (item.hasSubMenu()) { 335038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); 336038f1c80af06da55056120e121d43e3ee89ec726Adam Powell subMenu.saveActionViewStates(outStates); 337038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 338038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 339038f1c80af06da55056120e121d43e3ee89ec726Adam Powell 340038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (viewStates != null) { 341038f1c80af06da55056120e121d43e3ee89ec726Adam Powell outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates); 342038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 343038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 344038f1c80af06da55056120e121d43e3ee89ec726Adam Powell 345038f1c80af06da55056120e121d43e3ee89ec726Adam Powell public void restoreActionViewStates(Bundle states) { 346038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (states == null) { 347038f1c80af06da55056120e121d43e3ee89ec726Adam Powell return; 348038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 349038f1c80af06da55056120e121d43e3ee89ec726Adam Powell 350038f1c80af06da55056120e121d43e3ee89ec726Adam Powell SparseArray<Parcelable> viewStates = states.getSparseParcelableArray( 351038f1c80af06da55056120e121d43e3ee89ec726Adam Powell getActionViewStatesKey()); 352038f1c80af06da55056120e121d43e3ee89ec726Adam Powell 353038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final int itemCount = size(); 354038f1c80af06da55056120e121d43e3ee89ec726Adam Powell for (int i = 0; i < itemCount; i++) { 355038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final MenuItem item = getItem(i); 356038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final View v = item.getActionView(); 357038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (v != null && v.getId() != View.NO_ID) { 358038f1c80af06da55056120e121d43e3ee89ec726Adam Powell v.restoreHierarchyState(viewStates); 359038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 360038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (item.hasSubMenu()) { 361038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); 362038f1c80af06da55056120e121d43e3ee89ec726Adam Powell subMenu.restoreActionViewStates(states); 363038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 364038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 365038f1c80af06da55056120e121d43e3ee89ec726Adam Powell 366038f1c80af06da55056120e121d43e3ee89ec726Adam Powell final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID); 367038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (expandedId > 0) { 368038f1c80af06da55056120e121d43e3ee89ec726Adam Powell MenuItem itemToExpand = findItem(expandedId); 369038f1c80af06da55056120e121d43e3ee89ec726Adam Powell if (itemToExpand != null) { 370038f1c80af06da55056120e121d43e3ee89ec726Adam Powell itemToExpand.expandActionView(); 371038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 372038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 373038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 374038f1c80af06da55056120e121d43e3ee89ec726Adam Powell 375038f1c80af06da55056120e121d43e3ee89ec726Adam Powell protected String getActionViewStatesKey() { 376038f1c80af06da55056120e121d43e3ee89ec726Adam Powell return ACTION_VIEW_STATES_KEY; 377038f1c80af06da55056120e121d43e3ee89ec726Adam Powell } 378038f1c80af06da55056120e121d43e3ee89ec726Adam Powell 379696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void setCallback(Callback cb) { 380696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mCallback = cb; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Adds an item to the menu. The other add methods funnel to this. 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int ordering = getOrdering(categoryOrder); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3894d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder, 3904d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell ordering, title, mDefaultShowAsAction); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCurrentMenuInfo != null) { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Pass along the current menu info 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item.setMenuInfo(mCurrentMenuInfo); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItems.add(findInsertIndex(mItems, ordering), item); 398696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell onItemsChanged(true); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return item; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuItem add(CharSequence title) { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return addInternal(0, 0, 0, title); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuItem add(int titleRes) { 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return addInternal(0, 0, 0, mResources.getString(titleRes)); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuItem add(int group, int id, int categoryOrder, CharSequence title) { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return addInternal(group, id, categoryOrder, title); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuItem add(int group, int id, int categoryOrder, int title) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return addInternal(group, id, categoryOrder, mResources.getString(title)); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SubMenu addSubMenu(CharSequence title) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return addSubMenu(0, 0, 0, title); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SubMenu addSubMenu(int titleRes) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return addSubMenu(0, 0, 0, mResources.getString(titleRes)); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item); 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item.setSubMenu(subMenu); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return subMenu; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) { 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return addSubMenu(group, id, categoryOrder, mResources.getString(title)); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller, 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PackageManager pm = mContext.getPackageManager(); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final List<ResolveInfo> lri = 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pm.queryIntentActivityOptions(caller, specifics, intent, 0); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = lri != null ? lri.size() : 0; 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & FLAG_APPEND_TO_GROUP) == 0) { 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeGroup(group); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ResolveInfo ri = lri.get(i); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent rintent = new Intent( 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rintent.setComponent(new ComponentName( 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ri.activityInfo.applicationInfo.packageName, 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ri.activityInfo.name)); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm)) 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .setIcon(ri.loadIcon(pm)) 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .setIntent(rintent); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (outSpecificItems != null && ri.specificIndex >= 0) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project outSpecificItems[ri.specificIndex] = item; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return N; 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeItem(int id) { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeItemAtInt(findItemIndex(id), true); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeGroup(int group) { 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int i = findGroupIndex(group); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i >= 0) { 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int maxRemovable = mItems.size() - i; 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numRemoved = 0; 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't force update for each one, this method will do it at the end 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeItemAtInt(i, false); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify menu views 484696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell onItemsChanged(true); 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove the item at the given index and optionally forces menu views to 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * update. 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index The index of the item to be removed. If this index is 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * invalid an exception is thrown. 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param updateChildrenOnMenuViews Whether to force update on menu views. 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Please make sure you eventually call this after your batch of 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * removals. 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) { 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((index < 0) || (index >= mItems.size())) return; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItems.remove(index); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 503696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (updateChildrenOnMenuViews) onItemsChanged(true); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeItemAt(int index) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeItemAtInt(index, true); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearAll() { 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPreventDispatchingItemsChanged = true; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clear(); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clearHeader(); 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPreventDispatchingItemsChanged = false; 515696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mItemsChangedWhileDispatchPrevented = false; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onItemsChanged(true); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clear() { 5206b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell if (mExpandedItem != null) { 5216b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell collapseItemActionView(mExpandedItem); 5226b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItems.clear(); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onItemsChanged(true); 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void setExclusiveItemChecked(MenuItem item) { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int group = item.getGroupId(); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = mItems.size(); 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl curItem = mItems.get(i); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (curItem.getGroupId() == group) { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!curItem.isExclusiveCheckable()) continue; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!curItem.isCheckable()) continue; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check the item meant to be checked, uncheck the others (that are in the group) 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project curItem.setCheckedInt(curItem == item); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGroupCheckable(int group, boolean checkable, boolean exclusive) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = mItems.size(); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item = mItems.get(i); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.getGroupId() == group) { 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item.setExclusiveCheckable(exclusive); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item.setCheckable(checkable); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGroupVisible(int group, boolean visible) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = mItems.size(); 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We handle the notification of items being changed ourselves, so we use setVisibleInt rather 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // than setVisible and at the end notify of items being changed 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean changedAtLeastOneItem = false; 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item = mItems.get(i); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.getGroupId() == group) { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.setVisibleInt(visible)) changedAtLeastOneItem = true; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 57023f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell if (changedAtLeastOneItem) onItemsChanged(true); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGroupEnabled(int group, boolean enabled) { 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = mItems.size(); 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item = mItems.get(i); 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.getGroupId() == group) { 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item.setEnabled(enabled); 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean hasVisibleItems() { 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int size = size(); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item = mItems.get(i); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.isVisible()) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuItem findItem(int id) { 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int size = size(); 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item = mItems.get(i); 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.getItemId() == id) { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return item; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (item.hasSubMenu()) { 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItem possibleItem = item.getSubMenu().findItem(id); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (possibleItem != null) { 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return possibleItem; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int findItemIndex(int id) { 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int size = size(); 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item = mItems.get(i); 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.getItemId() == id) { 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return i; 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int findGroupIndex(int group) { 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return findGroupIndex(group, 0); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int findGroupIndex(int group, int start) { 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int size = size(); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start < 0) { 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start = 0; 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = start; i < size; i++) { 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final MenuItemImpl item = mItems.get(i); 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.getGroupId() == group) { 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return i; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int size() { 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mItems.size(); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuItem getItem(int index) { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mItems.get(index); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isShortcutKey(int keyCode, KeyEvent event) { 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return findItemWithShortcutForKey(keyCode, event) != null; 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setQwertyMode(boolean isQwerty) { 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mQwertyMode = isQwerty; 665696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 666696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell onItemsChanged(false); 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the ordering across all items. This will grab the category from 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the upper bits, find out how to order the category with respect to other 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * categories, and combine it with the lower bits. 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param categoryOrder The category order for a particular item (if it has 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not been or/add with a category, the default category is 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * assumed). 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An ordering integer that can be used to order this item across 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all the items (even from other categories). 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 680696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell private static int getOrdering(int categoryOrder) { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT; 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0 || index >= sCategoryToOrder.length) { 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("order does not contain a valid category."); 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether the menu shortcuts are in qwerty mode or not 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isQwertyMode() { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mQwertyMode; 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets whether the shortcuts should be visible on menus. Devices without hardware 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * key input will never make shortcuts visible even if this method is passed 'true'. 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param shortcutsVisible Whether shortcuts should be visible (if true and a 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * menu item does not have a shortcut defined, that item will 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * still NOT show a shortcut) 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setShortcutsVisible(boolean shortcutsVisible) { 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mShortcutsVisible == shortcutsVisible) return; 7074aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown 7084aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown setShortcutsVisibleInner(shortcutsVisible); 709696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell onItemsChanged(false); 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7124aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown private void setShortcutsVisibleInner(boolean shortcutsVisible) { 7134aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown mShortcutsVisible = shortcutsVisible 7144aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS 7154aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown && mResources.getBoolean( 7164aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown com.android.internal.R.bool.config_showMenuShortcutsWhenKeyboardPresent); 7174aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown } 7184aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether shortcuts should be visible on menus. 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isShortcutsVisible() { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mShortcutsVisible; 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Resources getResources() { 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mResources; 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Context getContext() { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mContext; 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 734696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) { 735696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell return mCallback != null && mCallback.onMenuItemSelected(menu, item); 736696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 737696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 738696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell /** 739696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Dispatch a mode change event to this menu's callback. 740696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell */ 741696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void changeMenuMode() { 742696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (mCallback != null) { 743696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mCallback.onMenuModeChange(this); 744696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 745696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 746696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) { 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = items.size() - 1; i >= 0; i--) { 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item = items.get(i); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.getOrdering() <= ordering) { 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return i + 1; 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performShortcut(int keyCode, KeyEvent event, int flags) { 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event); 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handled = false; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item != null) { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = performItemAction(item, flags); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(true); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return handled; 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 774e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard /* 775e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * This function will return all the menu and sub-menu items that can 776e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * be directly (the shortcut directly corresponds) and indirectly 777e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * (the ALT-enabled char corresponds to the shortcut) associated 778e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * with the keyCode. 779e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard */ 780696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) { 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean qwerty = isQwertyMode(); 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int metaState = event.getMetaState(); 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the chars associated with the keyCode (i.e using any chording combo) 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean isKeyCodeMapped = event.getKeyData(possibleChars); 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The delete key is not mapped to '\b' so we treat it specially 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) { 788696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell return; 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Look for an item whose shortcut is this key. 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = mItems.size(); 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item = mItems.get(i); 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.hasSubMenu()) { 796696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell ((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event); 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 798e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut(); 799e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) && 800e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard (shortcutChar != 0) && 801e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard (shortcutChar == possibleChars.meta[0] 802e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard || shortcutChar == possibleChars.meta[2] 803e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard || (qwerty && shortcutChar == '\b' && 804e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard keyCode == KeyEvent.KEYCODE_DEL)) && 805e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard item.isEnabled()) { 806e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard items.add(item); 807e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard } 808e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard } 809e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard } 810e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard 811e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard /* 812e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * We want to return the menu item associated with the key, but if there is no 813e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * ambiguity (i.e. there is only one menu item corresponding to the key) we want 814e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * to return it even if it's not an exact match; this allow the user to 815e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * _not_ use the ALT key for example, making the use of shortcuts slightly more 816e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * user-friendly. An example is on the G1, '!' and '1' are on the same key, and 817e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut). 818e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * 819e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * On the other hand, if two (or more) shortcuts corresponds to the same key, 820e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard * we have to only return the exact match. 821e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard */ 822e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) { 823e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard // Get all items that can be associated directly or indirectly with the keyCode 824696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell ArrayList<MenuItemImpl> items = mTempShortcutItemList; 825696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell items.clear(); 826696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell findItemsWithShortcutForKey(items, keyCode, event); 827e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard 828696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (items.isEmpty()) { 829e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard return null; 830e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard } 831e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard 832e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard final int metaState = event.getMetaState(); 833e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); 834e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard // Get the chars associated with the keyCode (i.e using any chording combo) 835e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard event.getKeyData(possibleChars); 836e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard 837e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard // If we have only one element, we can safely returns it 838696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final int size = items.size(); 839696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (size == 1) { 840e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard return items.get(0); 841e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard } 842e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard 843e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard final boolean qwerty = isQwertyMode(); 844e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard // If we found more than one item associated with the key, 845e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard // we have to return the exact match 846696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell for (int i = 0; i < size; i++) { 847696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final MenuItemImpl item = items.get(i); 848696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : 849696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell item.getNumericShortcut(); 850e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard if ((shortcutChar == possibleChars.meta[0] && 851e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard (metaState & KeyEvent.META_ALT_ON) == 0) 852e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard || (shortcutChar == possibleChars.meta[2] && 853e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard (metaState & KeyEvent.META_ALT_ON) != 0) 854e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard || (qwerty && shortcutChar == '\b' && 855e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard keyCode == KeyEvent.KEYCODE_DEL)) { 856e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard return item; 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 861e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performIdentifierAction(int id, int flags) { 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Look for an item whose identifier is the id. 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return performItemAction(findItem(id), flags); 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performItemAction(MenuItem item, int flags) { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl itemImpl = (MenuItemImpl) item; 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (itemImpl == null || !itemImpl.isEnabled()) { 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 8728d02deabac62c4a68a335a7b3141795466362b89Adam Powell } 87376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean invoked = itemImpl.invoke(); 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 876f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell final ActionProvider provider = item.getActionProvider(); 877f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell final boolean providerHasSubMenu = provider != null && provider.hasSubMenu(); 8788d02deabac62c4a68a335a7b3141795466362b89Adam Powell if (itemImpl.hasCollapsibleActionView()) { 8798d02deabac62c4a68a335a7b3141795466362b89Adam Powell invoked |= itemImpl.expandActionView(); 8808d02deabac62c4a68a335a7b3141795466362b89Adam Powell if (invoked) close(true); 881f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell } else if (itemImpl.hasSubMenu() || providerHasSubMenu) { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(false); 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 884f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell if (!itemImpl.hasSubMenu()) { 885f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell itemImpl.setSubMenu(new SubMenuBuilder(getContext(), this, itemImpl)); 886f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell } 887f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell 888f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell final SubMenuBuilder subMenu = (SubMenuBuilder) itemImpl.getSubMenu(); 889f77f480800a84ceb377e47cc200baf2bae4f5d9aAdam Powell if (providerHasSubMenu) { 890961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell provider.onPrepareSubMenu(subMenu); 891961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell } 892961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell invoked |= dispatchSubMenuSelected(subMenu); 893696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (!invoked) close(true); 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) { 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(true); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return invoked; 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Closes the visible menu. 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param allMenusAreClosing Whether the menus are completely closing (true), 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or whether there is another menu coming in this menu's place 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (false). For example, if the menu is closing because a 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sub menu is about to be shown, <var>allMenusAreClosing</var> 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is false. 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final void close(boolean allMenusAreClosing) { 913696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (mIsClosing) return; 914696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 915696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mIsClosing = true; 916696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 917696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final MenuPresenter presenter = ref.get(); 918696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (presenter == null) { 919696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenters.remove(ref); 920696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } else { 921696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell presenter.onCloseMenu(this, allMenusAreClosing); 922696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 924696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mIsClosing = false; 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(true); 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called when an item is added or removed. 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 935696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * @param structureChanged true if the menu structure changed, 936696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * false if only item properties changed. 93723f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell * (Visibility is a structural property since it affects layout.) 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 939696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell void onItemsChanged(boolean structureChanged) { 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mPreventDispatchingItemsChanged) { 941696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (structureChanged) { 942696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mIsVisibleItemsStale = true; 943696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mIsActionItemsStale = true; 944696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 9451821ff9022f0ea5f5c5d82a96a05f46192d50c26Adam Powell 946696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell dispatchPresenterUpdate(structureChanged); 947696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } else { 948696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mItemsChangedWhileDispatchPrevented = true; 949696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 950696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 9511821ff9022f0ea5f5c5d82a96a05f46192d50c26Adam Powell 952696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell /** 953696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Stop dispatching item changed events to presenters until 954696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * {@link #startDispatchingItemsChanged()} is called. Useful when 955696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * many menu operations are going to be performed as a batch. 956696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell */ 957696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void stopDispatchingItemsChanged() { 958a86b350977be53146d568bc0736d0f2b4aef8de5Adam Powell if (!mPreventDispatchingItemsChanged) { 959a86b350977be53146d568bc0736d0f2b4aef8de5Adam Powell mPreventDispatchingItemsChanged = true; 960a86b350977be53146d568bc0736d0f2b4aef8de5Adam Powell mItemsChangedWhileDispatchPrevented = false; 961a86b350977be53146d568bc0736d0f2b4aef8de5Adam Powell } 962696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 963696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 964696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void startDispatchingItemsChanged() { 965696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPreventDispatchingItemsChanged = false; 966696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 967696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (mItemsChangedWhileDispatchPrevented) { 968696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mItemsChangedWhileDispatchPrevented = false; 969696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell onItemsChanged(true); 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called by {@link MenuItemImpl} when its visible flag is changed. 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param item The item that has gone through a visibility change. 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onItemVisibleChanged(MenuItemImpl item) { 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify of items being changed 979696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mIsVisibleItemsStale = true; 98023f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell onItemsChanged(true); 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 98396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell /** 98496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Called by {@link MenuItemImpl} when its action request status is changed. 98596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * @param item The item that has gone through a change in action request status. 98696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */ 98796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell void onItemActionRequestChanged(MenuItemImpl item) { 98896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell // Notify of items being changed 989696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mIsActionItemsStale = true; 99023f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell onItemsChanged(true); 99196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 99296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<MenuItemImpl> getVisibleItems() { 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mIsVisibleItemsStale) return mVisibleItems; 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Refresh the visible items 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVisibleItems.clear(); 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int itemsSize = mItems.size(); 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MenuItemImpl item; 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < itemsSize; i++) { 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item = mItems.get(i); 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (item.isVisible()) mVisibleItems.add(item); 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsVisibleItemsStale = false; 100796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell mIsActionItemsStale = true; 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mVisibleItems; 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 101136fced9b211255e2137014e21fb3259042d8da85Adam Powell 101236fced9b211255e2137014e21fb3259042d8da85Adam Powell /** 101336fced9b211255e2137014e21fb3259042d8da85Adam Powell * This method determines which menu items get to be 'action items' that will appear 101436fced9b211255e2137014e21fb3259042d8da85Adam Powell * in an action bar and which items should be 'overflow items' in a secondary menu. 101536fced9b211255e2137014e21fb3259042d8da85Adam Powell * The rules are as follows: 101636fced9b211255e2137014e21fb3259042d8da85Adam Powell * 101736fced9b211255e2137014e21fb3259042d8da85Adam Powell * <p>Items are considered for inclusion in the order specified within the menu. 101836fced9b211255e2137014e21fb3259042d8da85Adam Powell * There is a limit of mMaxActionItems as a total count, optionally including the overflow 101936fced9b211255e2137014e21fb3259042d8da85Adam Powell * menu button itself. This is a soft limit; if an item shares a group ID with an item 102036fced9b211255e2137014e21fb3259042d8da85Adam Powell * previously included as an action item, the new item will stay with its group and become 102136fced9b211255e2137014e21fb3259042d8da85Adam Powell * an action item itself even if it breaks the max item count limit. This is done to 102236fced9b211255e2137014e21fb3259042d8da85Adam Powell * limit the conceptual complexity of the items presented within an action bar. Only a few 102336fced9b211255e2137014e21fb3259042d8da85Adam Powell * unrelated concepts should be presented to the user in this space, and groups are treated 102436fced9b211255e2137014e21fb3259042d8da85Adam Powell * as a single concept. 102536fced9b211255e2137014e21fb3259042d8da85Adam Powell * 102636fced9b211255e2137014e21fb3259042d8da85Adam Powell * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This 102736fced9b211255e2137014e21fb3259042d8da85Adam Powell * limit may be broken by a single item that exceeds the remaining space, but no further 102836fced9b211255e2137014e21fb3259042d8da85Adam Powell * items may be added. If an item that is part of a group cannot fit within the remaining 102936fced9b211255e2137014e21fb3259042d8da85Adam Powell * measured width, the entire group will be demoted to overflow. This is done to ensure room 103036fced9b211255e2137014e21fb3259042d8da85Adam Powell * for navigation and other affordances in the action bar as well as reduce general UI clutter. 103136fced9b211255e2137014e21fb3259042d8da85Adam Powell * 103236fced9b211255e2137014e21fb3259042d8da85Adam Powell * <p>The space freed by demoting a full group cannot be consumed by future menu items. 103336fced9b211255e2137014e21fb3259042d8da85Adam Powell * Once items begin to overflow, all future items become overflow items as well. This is 103436fced9b211255e2137014e21fb3259042d8da85Adam Powell * to avoid inadvertent reordering that may break the app's intended design. 103536fced9b211255e2137014e21fb3259042d8da85Adam Powell */ 1036696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void flagActionItems() { 103796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell if (!mIsActionItemsStale) { 103896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell return; 103996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 10408028dd32a4a04154050220dd0693583d5b750330Adam Powell 1041696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell // Presenters flag action items as needed. 1042696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell boolean flagged = false; 1043696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 1044696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final MenuPresenter presenter = ref.get(); 1045696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (presenter == null) { 1046696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenters.remove(ref); 10478028dd32a4a04154050220dd0693583d5b750330Adam Powell } else { 1048696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell flagged |= presenter.flagActionItems(); 104996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 105096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 10518028dd32a4a04154050220dd0693583d5b750330Adam Powell 1052696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (flagged) { 1053696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mActionItems.clear(); 1054696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mNonActionItems.clear(); 1055696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell ArrayList<MenuItemImpl> visibleItems = getVisibleItems(); 1056696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final int itemsSize = visibleItems.size(); 1057696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell for (int i = 0; i < itemsSize; i++) { 1058696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell MenuItemImpl item = visibleItems.get(i); 1059696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (item.isActionButton()) { 1060696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mActionItems.add(item); 1061696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } else { 1062696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mNonActionItems.add(item); 106336fced9b211255e2137014e21fb3259042d8da85Adam Powell } 106496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 106504dc06f52a68299c0ad70fa0a9f204d99983ba2bAdam Powell } else { 106604dc06f52a68299c0ad70fa0a9f204d99983ba2bAdam Powell // Nobody flagged anything, everything is a non-action item. 1067696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell // (This happens during a first pass with no action-item presenters.) 1068696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mActionItems.clear(); 1069696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mNonActionItems.clear(); 1070696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mNonActionItems.addAll(getVisibleItems()); 107196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 107296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell mIsActionItemsStale = false; 107396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 107496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell 1075696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell ArrayList<MenuItemImpl> getActionItems() { 1076696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell flagActionItems(); 107796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell return mActionItems; 107896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 107996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell 1080696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell ArrayList<MenuItemImpl> getNonActionItems() { 1081696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell flagActionItems(); 108296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell return mNonActionItems; 108396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell } 108436fced9b211255e2137014e21fb3259042d8da85Adam Powell 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearHeader() { 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderIcon = null; 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderTitle = null; 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderView = null; 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onItemsChanged(false); 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes, 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Drawable icon, final View view) { 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Resources r = getResources(); 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderView = view; 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If using a custom view, then the title and icon aren't used 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderTitle = null; 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderIcon = null; 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (titleRes > 0) { 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderTitle = r.getText(titleRes); 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (title != null) { 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderTitle = title; 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (iconRes > 0) { 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderIcon = r.getDrawable(iconRes); 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (icon != null) { 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderIcon = icon; 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If using the title or icon, then a custom view isn't used 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderView = null; 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify of change 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onItemsChanged(false); 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the header's title. This replaces the header view. Called by the 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * builder-style methods of subclasses. 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param title The new title. 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return This MenuBuilder so additional setters can be called. 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected MenuBuilder setHeaderTitleInt(CharSequence title) { 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setHeaderInternal(0, title, 0, null, null); 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the header's title. This replaces the header view. Called by the 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * builder-style methods of subclasses. 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param titleRes The new title (as a resource ID). 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return This MenuBuilder so additional setters can be called. 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected MenuBuilder setHeaderTitleInt(int titleRes) { 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setHeaderInternal(titleRes, null, 0, null, null); 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the header's icon. This replaces the header view. Called by the 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * builder-style methods of subclasses. 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param icon The new icon. 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return This MenuBuilder so additional setters can be called. 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected MenuBuilder setHeaderIconInt(Drawable icon) { 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setHeaderInternal(0, null, 0, icon, null); 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the header's icon. This replaces the header view. Called by the 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * builder-style methods of subclasses. 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param iconRes The new icon (as a resource ID). 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return This MenuBuilder so additional setters can be called. 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected MenuBuilder setHeaderIconInt(int iconRes) { 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setHeaderInternal(0, null, iconRes, null, null); 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the header's view. This replaces the title and icon. Called by the 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * builder-style methods of subclasses. 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view The new view. 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return This MenuBuilder so additional setters can be called. 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected MenuBuilder setHeaderViewInt(View view) { 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setHeaderInternal(0, null, 0, null, view); 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence getHeaderTitle() { 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaderTitle; 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable getHeaderIcon() { 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaderIcon; 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View getHeaderView() { 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaderView; 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the root menu (if this is a submenu, find its root menu). 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The root menu. 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuBuilder getRootMenu() { 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the current menu info that is set on all items added to this menu 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (until this is called again with different menu info, in which case that 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * one will be added to all subsequent item additions). 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param menuInfo The extra menu information to add. 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCurrentMenuInfo(ContextMenuInfo menuInfo) { 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrentMenuInfo = menuInfo; 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void setOptionalIconsVisible(boolean visible) { 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOptionalIconsVisible = visible; 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean getOptionalIconsVisible() { 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mOptionalIconsVisible; 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12228d02deabac62c4a68a335a7b3141795466362b89Adam Powell 12238d02deabac62c4a68a335a7b3141795466362b89Adam Powell public boolean expandItemActionView(MenuItemImpl item) { 12248d02deabac62c4a68a335a7b3141795466362b89Adam Powell if (mPresenters.isEmpty()) return false; 12258d02deabac62c4a68a335a7b3141795466362b89Adam Powell 12268d02deabac62c4a68a335a7b3141795466362b89Adam Powell boolean expanded = false; 12278d02deabac62c4a68a335a7b3141795466362b89Adam Powell 12288d02deabac62c4a68a335a7b3141795466362b89Adam Powell stopDispatchingItemsChanged(); 12298d02deabac62c4a68a335a7b3141795466362b89Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 12308d02deabac62c4a68a335a7b3141795466362b89Adam Powell final MenuPresenter presenter = ref.get(); 12318d02deabac62c4a68a335a7b3141795466362b89Adam Powell if (presenter == null) { 12328d02deabac62c4a68a335a7b3141795466362b89Adam Powell mPresenters.remove(ref); 12338d02deabac62c4a68a335a7b3141795466362b89Adam Powell } else if ((expanded = presenter.expandItemActionView(this, item))) { 12348d02deabac62c4a68a335a7b3141795466362b89Adam Powell break; 12358d02deabac62c4a68a335a7b3141795466362b89Adam Powell } 12368d02deabac62c4a68a335a7b3141795466362b89Adam Powell } 12378d02deabac62c4a68a335a7b3141795466362b89Adam Powell startDispatchingItemsChanged(); 12388d02deabac62c4a68a335a7b3141795466362b89Adam Powell 12396b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell if (expanded) { 12406b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell mExpandedItem = item; 12416b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell } 12428d02deabac62c4a68a335a7b3141795466362b89Adam Powell return expanded; 12438d02deabac62c4a68a335a7b3141795466362b89Adam Powell } 12448d02deabac62c4a68a335a7b3141795466362b89Adam Powell 12458d02deabac62c4a68a335a7b3141795466362b89Adam Powell public boolean collapseItemActionView(MenuItemImpl item) { 12466b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell if (mPresenters.isEmpty() || mExpandedItem != item) return false; 12478d02deabac62c4a68a335a7b3141795466362b89Adam Powell 12488d02deabac62c4a68a335a7b3141795466362b89Adam Powell boolean collapsed = false; 12498d02deabac62c4a68a335a7b3141795466362b89Adam Powell 12508d02deabac62c4a68a335a7b3141795466362b89Adam Powell stopDispatchingItemsChanged(); 12518d02deabac62c4a68a335a7b3141795466362b89Adam Powell for (WeakReference<MenuPresenter> ref : mPresenters) { 12528d02deabac62c4a68a335a7b3141795466362b89Adam Powell final MenuPresenter presenter = ref.get(); 12538d02deabac62c4a68a335a7b3141795466362b89Adam Powell if (presenter == null) { 12548d02deabac62c4a68a335a7b3141795466362b89Adam Powell mPresenters.remove(ref); 12558d02deabac62c4a68a335a7b3141795466362b89Adam Powell } else if ((collapsed = presenter.collapseItemActionView(this, item))) { 12568d02deabac62c4a68a335a7b3141795466362b89Adam Powell break; 12578d02deabac62c4a68a335a7b3141795466362b89Adam Powell } 12588d02deabac62c4a68a335a7b3141795466362b89Adam Powell } 12598d02deabac62c4a68a335a7b3141795466362b89Adam Powell startDispatchingItemsChanged(); 12608d02deabac62c4a68a335a7b3141795466362b89Adam Powell 12616b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell if (collapsed) { 12626b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell mExpandedItem = null; 12636b0e97c7c48cf9446c7d4bc1b37d4c37d78433b0Adam Powell } 12648d02deabac62c4a68a335a7b3141795466362b89Adam Powell return collapsed; 12658d02deabac62c4a68a335a7b3141795466362b89Adam Powell } 1266275702c2f47ed87ab642462530092d9777f32ecdAdam Powell 1267275702c2f47ed87ab642462530092d9777f32ecdAdam Powell public MenuItemImpl getExpandedItem() { 1268275702c2f47ed87ab642462530092d9777f32ecdAdam Powell return mExpandedItem; 1269275702c2f47ed87ab642462530092d9777f32ecdAdam Powell } 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1271