MenuBuilder.java revision 961dd11895ce72e59bca124ef5bea4e4c1183099
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 {
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String LOGTAG = "MenuBuilder";
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    private static final String PRESENTER_KEY = "android:menu:presenters";
5311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[]  sCategoryToOrder = new int[] {
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        1, /* No category */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        4, /* CONTAINER */
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        5, /* SYSTEM */
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        3, /* SECONDARY */
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        2, /* ALTERNATIVE */
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0, /* SELECTED_ALTERNATIVE */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Resources mResources;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode()
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of accessing this directly.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mQwertyMode;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the shortcuts should be visible on menus. Use isShortcutsVisible()
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of accessing this directly.
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mShortcutsVisible;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Callback that will receive the various menu-related events generated by
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this class. Use getCallback to get a reference to the callback.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Callback mCallback;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Contains all of the items for this menu */
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<MenuItemImpl> mItems;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Contains only the items that are currently visible.  This will be created/refreshed from
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getVisibleItems()} */
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<MenuItemImpl> mVisibleItems;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether or not the items (or any one item's shown state) has changed since it was last
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fetched from {@link #getVisibleItems()}
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsVisibleItemsStale;
9596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
9696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
9796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Contains only the items that should appear in the Action Bar, if present.
9896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
9996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private ArrayList<MenuItemImpl> mActionItems;
10096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
10196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Contains items that should NOT appear in the Action Bar, if present.
10296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
10396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private ArrayList<MenuItemImpl> mNonActionItems;
104696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
10536fced9b211255e2137014e21fb3259042d8da85Adam Powell    /**
10696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Whether or not the items (or any one item's action state) has changed since it was
10796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * last fetched.
10896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
10996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private boolean mIsActionItemsStale;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1124d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell     * Default value for how added items should show in the action list.
1134d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell     */
1144d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell    private int mDefaultShowAsAction = MenuItem.SHOW_AS_ACTION_NEVER;
1154d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell
1164d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell    /**
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Current use case is Context Menus: As Views populate the context menu, each one has
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extra information that should be passed along.  This is the current menu info that
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should be set on all items added to this menu.
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ContextMenuInfo mCurrentMenuInfo;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header title for menu types that have a header (context and submenus) */
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CharSequence mHeaderTitle;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header icon for menu types that have a header and support icons (context) */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Drawable mHeaderIcon;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header custom view for menu types that have a header and support custom views (context) */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mHeaderView;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Contains the state of the View hierarchy for all menu views when the menu
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was frozen.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SparseArray<Parcelable> mFrozenViewStates;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Prevents onItemsChanged from doing its junk, useful for batching commands
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that may individually call onItemsChanged.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mPreventDispatchingItemsChanged = false;
141696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private boolean mItemsChangedWhileDispatchPrevented = false;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mOptionalIconsVisible = false;
1442fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell
145696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private boolean mIsClosing = false;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
147696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private ArrayList<MenuItemImpl> mTempShortcutItemList = new ArrayList<MenuItemImpl>();
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
149696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private CopyOnWriteArrayList<WeakReference<MenuPresenter>> mPresenters =
150696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            new CopyOnWriteArrayList<WeakReference<MenuPresenter>>();
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
153696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Called by menu to notify of close and selection changes.
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Callback {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a menu item is selected.
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu The menu that is the parent of the item
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param item The menu item that is selected
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return whether the menu item selection was handled
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when the mode of the menu changes (for example, from icon to expanded).
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu the menu that has changed modes
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onMenuModeChange(MenuBuilder menu);
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by menu items to execute their associated action
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface ItemInvoker {
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean invokeItem(MenuItemImpl item);
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuBuilder(Context context) {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResources = context.getResources();
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems = new ArrayList<MenuItemImpl>();
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVisibleItems = new ArrayList<MenuItemImpl>();
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsVisibleItemsStale = true;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mActionItems = new ArrayList<MenuItemImpl>();
18996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mNonActionItems = new ArrayList<MenuItemImpl>();
19096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = true;
19196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
1924aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown        setShortcutsVisibleInner(true);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1954d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell    public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
1964d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell        mDefaultShowAsAction = defaultShowAsAction;
1974d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell        return this;
1984d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell    }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
200696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
201696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Add a presenter to this menu. This will only hold a WeakReference;
202696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * you do not need to explicitly remove a presenter, but you can using
203696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * {@link #removeMenuPresenter(MenuPresenter)}.
204696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     *
205696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @param presenter The presenter to add
206696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
207696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void addMenuPresenter(MenuPresenter presenter) {
208696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenters.add(new WeakReference<MenuPresenter>(presenter));
209696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        presenter.initForMenu(mContext, this);
210696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mIsActionItemsStale = true;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
212696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
214696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Remove a presenter from this menu. That presenter will no longer
215696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * receive notifications of updates to this menu's data.
216696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     *
217696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @param presenter The presenter to remove
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
219696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void removeMenuPresenter(MenuPresenter presenter) {
220696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
221696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final MenuPresenter item = ref.get();
222696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (item == null || item == presenter) {
223696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                mPresenters.remove(ref);
224696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
228696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private void dispatchPresenterUpdate(boolean cleared) {
229696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mPresenters.isEmpty()) return;
230696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
231640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        stopDispatchingItemsChanged();
232696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
233696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final MenuPresenter presenter = ref.get();
234696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (presenter == null) {
235696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                mPresenters.remove(ref);
236696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            } else {
237696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                presenter.updateMenuView(cleared);
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
240640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        startDispatchingItemsChanged();
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
243696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) {
244696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mPresenters.isEmpty()) return false;
245696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
246696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        boolean result = false;
247696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
248696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
249696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final MenuPresenter presenter = ref.get();
250696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (presenter == null) {
251696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                mPresenters.remove(ref);
252696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            } else if (!result) {
253696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                result = presenter.onSubMenuSelected(subMenu);
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
256696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return result;
257696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
258696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
25911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    private void dispatchSaveInstanceState(Bundle outState) {
26011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        if (mPresenters.isEmpty()) return;
26111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
26211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();
26311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
26411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
26511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            final MenuPresenter presenter = ref.get();
26611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            if (presenter == null) {
26711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                mPresenters.remove(ref);
26811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            } else {
26911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                final int id = presenter.getId();
27011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                if (id > 0) {
27111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                    final Parcelable state = presenter.onSaveInstanceState();
27211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                    if (state != null) {
27311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                        presenterStates.put(id, state);
27411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                    }
27511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                }
27611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            }
27711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
27811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
27911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
28011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
28111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
28211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    private void dispatchRestoreInstanceState(Bundle state) {
28311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);
28411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
28511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        if (presenterStates == null || mPresenters.isEmpty()) return;
28611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
28711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
28811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            final MenuPresenter presenter = ref.get();
28911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            if (presenter == null) {
29011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                mPresenters.remove(ref);
29111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            } else {
29211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                final int id = presenter.getId();
29311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                if (id > 0) {
29411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                    Parcelable parcel = presenterStates.get(id);
29511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                    if (parcel != null) {
29611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                        presenter.onRestoreInstanceState(parcel);
29711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                    }
29811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell                }
29911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell            }
30011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        }
30111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
30211ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
30311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    public void savePresenterStates(Bundle outState) {
30411ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        dispatchSaveInstanceState(outState);
30511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
30611ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
30711ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    public void restorePresenterStates(Bundle state) {
30811ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell        dispatchRestoreInstanceState(state);
30911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
31011ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
311696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void setCallback(Callback cb) {
312696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mCallback = cb;
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Adds an item to the menu.  The other add methods funnel to this.
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int ordering = getOrdering(categoryOrder);
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3214d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell        final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder,
3224d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell                ordering, title, mDefaultShowAsAction);
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrentMenuInfo != null) {
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Pass along the current menu info
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.setMenuInfo(mCurrentMenuInfo);
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.add(findInsertIndex(mItems, ordering), item);
330696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        onItemsChanged(true);
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return item;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(CharSequence title) {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(0, 0, 0, title);
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int titleRes) {
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(0, 0, 0, mResources.getString(titleRes));
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(group, id, categoryOrder, title);
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int group, int id, int categoryOrder, int title) {
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(group, id, categoryOrder, mResources.getString(title));
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(CharSequence title) {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(0, 0, 0, title);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int titleRes) {
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        item.setSubMenu(subMenu);
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return subMenu;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PackageManager pm = mContext.getPackageManager();
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final List<ResolveInfo> lri =
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = lri != null ? lri.size() : 0;
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            removeGroup(group);
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ResolveInfo ri = lri.get(i);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent rintent = new Intent(
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rintent.setComponent(new ComponentName(
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.applicationInfo.packageName,
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.name));
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .setIcon(ri.loadIcon(pm))
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .setIntent(rintent);
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outSpecificItems != null && ri.specificIndex >= 0) {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outSpecificItems[ri.specificIndex] = item;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return N;
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeItem(int id) {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeItemAtInt(findItemIndex(id), true);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGroup(int group) {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int i = findGroupIndex(group);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i >= 0) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int maxRemovable = mItems.size() - i;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int numRemoved = 0;
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't force update for each one, this method will do it at the end
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeItemAtInt(i, false);
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Notify menu views
416696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            onItemsChanged(true);
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove the item at the given index and optionally forces menu views to
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * update.
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param index The index of the item to be removed. If this index is
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            invalid an exception is thrown.
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param updateChildrenOnMenuViews Whether to force update on menu views.
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            Please make sure you eventually call this after your batch of
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            removals.
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((index < 0) || (index >= mItems.size())) return;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.remove(index);
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
435696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (updateChildrenOnMenuViews) onItemsChanged(true);
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeItemAt(int index) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeItemAtInt(index, true);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearAll() {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreventDispatchingItemsChanged = true;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clear();
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clearHeader();
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreventDispatchingItemsChanged = false;
447696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mItemsChangedWhileDispatchPrevented = false;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(true);
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clear() {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.clear();
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(true);
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setExclusiveItemChecked(MenuItem item) {
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int group = item.getGroupId();
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl curItem = mItems.get(i);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (curItem.getGroupId() == group) {
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!curItem.isExclusiveCheckable()) continue;
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!curItem.isCheckable()) continue;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check the item meant to be checked, uncheck the others (that are in the group)
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curItem.setCheckedInt(curItem == item);
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setExclusiveCheckable(exclusive);
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setCheckable(checkable);
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupVisible(int group, boolean visible) {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // than setVisible and at the end notify of items being changed
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changedAtLeastOneItem = false;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (changedAtLeastOneItem) onItemsChanged(false);
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupEnabled(int group, boolean enabled) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setEnabled(enabled);
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasVisibleItems() {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.isVisible()) {
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem findItem(int id) {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getItemId() == id) {
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return item;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (item.hasSubMenu()) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MenuItem possibleItem = item.getSubMenu().findItem(id);
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (possibleItem != null) {
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return possibleItem;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findItemIndex(int id) {
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getItemId() == id) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i;
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findGroupIndex(int group) {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return findGroupIndex(group, 0);
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findGroupIndex(int group, int start) {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (start < 0) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            start = 0;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = start; i < size; i++) {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final MenuItemImpl item = mItems.get(i);
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i;
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int size() {
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mItems.size();
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** {@inheritDoc} */
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem getItem(int index) {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mItems.get(index);
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShortcutKey(int keyCode, KeyEvent event) {
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return findItemWithShortcutForKey(keyCode, event) != null;
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setQwertyMode(boolean isQwerty) {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyMode = isQwerty;
594696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
595696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        onItemsChanged(false);
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the ordering across all items. This will grab the category from
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the upper bits, find out how to order the category with respect to other
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * categories, and combine it with the lower bits.
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param categoryOrder The category order for a particular item (if it has
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            not been or/add with a category, the default category is
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            assumed).
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return An ordering integer that can be used to order this item across
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         all the items (even from other categories).
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
609696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private static int getOrdering(int categoryOrder) {
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index < 0 || index >= sCategoryToOrder.length) {
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("order does not contain a valid category.");
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return whether the menu shortcuts are in qwerty mode or not
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean isQwertyMode() {
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mQwertyMode;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets whether the shortcuts should be visible on menus.  Devices without hardware
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * key input will never make shortcuts visible even if this method is passed 'true'.
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param shortcutsVisible Whether shortcuts should be visible (if true and a
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            menu item does not have a shortcut defined, that item will
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            still NOT show a shortcut)
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setShortcutsVisible(boolean shortcutsVisible) {
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShortcutsVisible == shortcutsVisible) return;
6364aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown
6374aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown        setShortcutsVisibleInner(shortcutsVisible);
638696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        onItemsChanged(false);
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6414aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown    private void setShortcutsVisibleInner(boolean shortcutsVisible) {
6424aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown        mShortcutsVisible = shortcutsVisible
6434aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown                && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS
6444aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown                && mResources.getBoolean(
6454aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown                        com.android.internal.R.bool.config_showMenuShortcutsWhenKeyboardPresent);
6464aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown    }
6474aed78b5056560f499e5953f659fa90a06ecc38aJeff Brown
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Whether shortcuts should be visible on menus.
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShortcutsVisible() {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mShortcutsVisible;
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Resources getResources() {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mResources;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
663696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) {
664696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return mCallback != null && mCallback.onMenuItemSelected(menu, item);
665696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
666696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
667696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
668696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Dispatch a mode change event to this menu's callback.
669696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
670696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void changeMenuMode() {
671696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mCallback != null) {
672696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mCallback.onMenuModeChange(this);
673696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
674696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
675696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = items.size() - 1; i >= 0; i--) {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = items.get(i);
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getOrdering() <= ordering) {
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i + 1;
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean handled = false;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (item != null) {
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handled = performItemAction(item, flags);
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(true);
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return handled;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
703e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    /*
704e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * This function will return all the menu and sub-menu items that can
705e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * be directly (the shortcut directly corresponds) and indirectly
706e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * (the ALT-enabled char corresponds to the shortcut) associated
707e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * with the keyCode.
708e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     */
709696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean qwerty = isQwertyMode();
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int metaState = event.getMetaState();
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get the chars associated with the keyCode (i.e using any chording combo)
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The delete key is not mapped to '\b' so we treat it specially
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
717696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return;
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Look for an item whose shortcut is this key.
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
725696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                ((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
727e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
728e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
729e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  (shortcutChar != 0) &&
730e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  (shortcutChar == possibleChars.meta[0]
731e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                      || shortcutChar == possibleChars.meta[2]
732e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                      || (qwerty && shortcutChar == '\b' &&
733e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                          keyCode == KeyEvent.KEYCODE_DEL)) &&
734e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  item.isEnabled()) {
735e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                items.add(item);
736e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            }
737e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
738e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    }
739e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
740e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    /*
741e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * We want to return the menu item associated with the key, but if there is no
742e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * ambiguity (i.e. there is only one menu item corresponding to the key) we want
743e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * to return it even if it's not an exact match; this allow the user to
744e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * _not_ use the ALT key for example, making the use of shortcuts slightly more
745e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
746e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
747e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     *
748e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * On the other hand, if two (or more) shortcuts corresponds to the same key,
749e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * we have to only return the exact match.
750e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     */
751e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
752e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // Get all items that can be associated directly or indirectly with the keyCode
753696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        ArrayList<MenuItemImpl> items = mTempShortcutItemList;
754696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        items.clear();
755696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        findItemsWithShortcutForKey(items, keyCode, event);
756e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
757696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (items.isEmpty()) {
758e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            return null;
759e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
760e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
761e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final int metaState = event.getMetaState();
762e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
763e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // Get the chars associated with the keyCode (i.e using any chording combo)
764e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        event.getKeyData(possibleChars);
765e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
766e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // If we have only one element, we can safely returns it
767696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final int size = items.size();
768696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (size == 1) {
769e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            return items.get(0);
770e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
771e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
772e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final boolean qwerty = isQwertyMode();
773e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // If we found more than one item associated with the key,
774e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // we have to return the exact match
775696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (int i = 0; i < size; i++) {
776696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final MenuItemImpl item = items.get(i);
777696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() :
778696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    item.getNumericShortcut();
779e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            if ((shortcutChar == possibleChars.meta[0] &&
780e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    (metaState & KeyEvent.META_ALT_ON) == 0)
781e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                || (shortcutChar == possibleChars.meta[2] &&
782e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    (metaState & KeyEvent.META_ALT_ON) != 0)
783e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                || (qwerty && shortcutChar == '\b' &&
784e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    keyCode == KeyEvent.KEYCODE_DEL)) {
785e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                return item;
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
790e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performIdentifierAction(int id, int flags) {
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Look for an item whose identifier is the id.
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return performItemAction(findItem(id), flags);
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performItemAction(MenuItem item, int flags) {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl itemImpl = (MenuItemImpl) item;
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (itemImpl == null || !itemImpl.isEnabled()) {
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8018d02deabac62c4a68a335a7b3141795466362b89Adam Powell        }
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean invoked = itemImpl.invoke();
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8058d02deabac62c4a68a335a7b3141795466362b89Adam Powell        if (itemImpl.hasCollapsibleActionView()) {
8068d02deabac62c4a68a335a7b3141795466362b89Adam Powell            invoked |= itemImpl.expandActionView();
8078d02deabac62c4a68a335a7b3141795466362b89Adam Powell            if (invoked) close(true);
8088d02deabac62c4a68a335a7b3141795466362b89Adam Powell        } else if (item.hasSubMenu()) {
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(false);
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
811961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell            final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
812961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell            final ActionProvider provider = item.getActionProvider();
813961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell            if (provider != null && provider.hasSubMenu()) {
814961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell                provider.onPrepareSubMenu(subMenu);
815961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell            }
816961dd11895ce72e59bca124ef5bea4e4c1183099Adam Powell            invoked |= dispatchSubMenuSelected(subMenu);
817696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (!invoked) close(true);
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                close(true);
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return invoked;
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Closes the visible menu.
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param allMenusAreClosing Whether the menus are completely closing (true),
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            or whether there is another menu coming in this menu's place
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            (false). For example, if the menu is closing because a
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            sub menu is about to be shown, <var>allMenusAreClosing</var>
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            is false.
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void close(boolean allMenusAreClosing) {
837696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mIsClosing) return;
838696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
839696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mIsClosing = true;
840696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
841696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final MenuPresenter presenter = ref.get();
842696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (presenter == null) {
843696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                mPresenters.remove(ref);
844696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            } else {
845696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                presenter.onCloseMenu(this, allMenusAreClosing);
846696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
848696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mIsClosing = false;
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** {@inheritDoc} */
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void close() {
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close(true);
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when an item is added or removed.
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
859696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * @param structureChanged true if the menu structure changed,
860696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     *                         false if only item properties changed.
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
862696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    void onItemsChanged(boolean structureChanged) {
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mPreventDispatchingItemsChanged) {
864696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (structureChanged) {
865696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                mIsVisibleItemsStale = true;
866696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                mIsActionItemsStale = true;
867696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
8681821ff9022f0ea5f5c5d82a96a05f46192d50c26Adam Powell
869696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            dispatchPresenterUpdate(structureChanged);
870696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        } else {
871696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mItemsChangedWhileDispatchPrevented = true;
872696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
873696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
8741821ff9022f0ea5f5c5d82a96a05f46192d50c26Adam Powell
875696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    /**
876696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * Stop dispatching item changed events to presenters until
877696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * {@link #startDispatchingItemsChanged()} is called. Useful when
878696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     * many menu operations are going to be performed as a batch.
879696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell     */
880696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void stopDispatchingItemsChanged() {
881a86b350977be53146d568bc0736d0f2b4aef8de5Adam Powell        if (!mPreventDispatchingItemsChanged) {
882a86b350977be53146d568bc0736d0f2b4aef8de5Adam Powell            mPreventDispatchingItemsChanged = true;
883a86b350977be53146d568bc0736d0f2b4aef8de5Adam Powell            mItemsChangedWhileDispatchPrevented = false;
884a86b350977be53146d568bc0736d0f2b4aef8de5Adam Powell        }
885696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
886696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
887696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void startDispatchingItemsChanged() {
888696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPreventDispatchingItemsChanged = false;
889696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
890696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mItemsChangedWhileDispatchPrevented) {
891696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mItemsChangedWhileDispatchPrevented = false;
892696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            onItemsChanged(true);
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by {@link MenuItemImpl} when its visible flag is changed.
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param item The item that has gone through a visibility change.
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void onItemVisibleChanged(MenuItemImpl item) {
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Notify of items being changed
902696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mIsVisibleItemsStale = true;
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
90696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
90796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Called by {@link MenuItemImpl} when its action request status is changed.
90896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * @param item The item that has gone through a change in action request status.
90996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
91096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    void onItemActionRequestChanged(MenuItemImpl item) {
91196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        // Notify of items being changed
912696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mIsActionItemsStale = true;
91396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        onItemsChanged(false);
91496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
91596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<MenuItemImpl> getVisibleItems() {
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mIsVisibleItemsStale) return mVisibleItems;
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Refresh the visible items
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVisibleItems.clear();
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int itemsSize = mItems.size();
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl item;
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < itemsSize; i++) {
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item = mItems.get(i);
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.isVisible()) mVisibleItems.add(item);
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsVisibleItemsStale = false;
93096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = true;
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mVisibleItems;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
93436fced9b211255e2137014e21fb3259042d8da85Adam Powell
93536fced9b211255e2137014e21fb3259042d8da85Adam Powell    /**
93636fced9b211255e2137014e21fb3259042d8da85Adam Powell     * This method determines which menu items get to be 'action items' that will appear
93736fced9b211255e2137014e21fb3259042d8da85Adam Powell     * in an action bar and which items should be 'overflow items' in a secondary menu.
93836fced9b211255e2137014e21fb3259042d8da85Adam Powell     * The rules are as follows:
93936fced9b211255e2137014e21fb3259042d8da85Adam Powell     *
94036fced9b211255e2137014e21fb3259042d8da85Adam Powell     * <p>Items are considered for inclusion in the order specified within the menu.
94136fced9b211255e2137014e21fb3259042d8da85Adam Powell     * There is a limit of mMaxActionItems as a total count, optionally including the overflow
94236fced9b211255e2137014e21fb3259042d8da85Adam Powell     * menu button itself. This is a soft limit; if an item shares a group ID with an item
94336fced9b211255e2137014e21fb3259042d8da85Adam Powell     * previously included as an action item, the new item will stay with its group and become
94436fced9b211255e2137014e21fb3259042d8da85Adam Powell     * an action item itself even if it breaks the max item count limit. This is done to
94536fced9b211255e2137014e21fb3259042d8da85Adam Powell     * limit the conceptual complexity of the items presented within an action bar. Only a few
94636fced9b211255e2137014e21fb3259042d8da85Adam Powell     * unrelated concepts should be presented to the user in this space, and groups are treated
94736fced9b211255e2137014e21fb3259042d8da85Adam Powell     * as a single concept.
94836fced9b211255e2137014e21fb3259042d8da85Adam Powell     *
94936fced9b211255e2137014e21fb3259042d8da85Adam Powell     * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This
95036fced9b211255e2137014e21fb3259042d8da85Adam Powell     * limit may be broken by a single item that exceeds the remaining space, but no further
95136fced9b211255e2137014e21fb3259042d8da85Adam Powell     * items may be added. If an item that is part of a group cannot fit within the remaining
95236fced9b211255e2137014e21fb3259042d8da85Adam Powell     * measured width, the entire group will be demoted to overflow. This is done to ensure room
95336fced9b211255e2137014e21fb3259042d8da85Adam Powell     * for navigation and other affordances in the action bar as well as reduce general UI clutter.
95436fced9b211255e2137014e21fb3259042d8da85Adam Powell     *
95536fced9b211255e2137014e21fb3259042d8da85Adam Powell     * <p>The space freed by demoting a full group cannot be consumed by future menu items.
95636fced9b211255e2137014e21fb3259042d8da85Adam Powell     * Once items begin to overflow, all future items become overflow items as well. This is
95736fced9b211255e2137014e21fb3259042d8da85Adam Powell     * to avoid inadvertent reordering that may break the app's intended design.
95836fced9b211255e2137014e21fb3259042d8da85Adam Powell     */
959696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void flagActionItems() {
96096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        if (!mIsActionItemsStale) {
96196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            return;
96296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
9638028dd32a4a04154050220dd0693583d5b750330Adam Powell
964696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        // Presenters flag action items as needed.
965696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        boolean flagged = false;
966696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
967696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final MenuPresenter presenter = ref.get();
968696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (presenter == null) {
969696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                mPresenters.remove(ref);
9708028dd32a4a04154050220dd0693583d5b750330Adam Powell            } else {
971696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                flagged |= presenter.flagActionItems();
97296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            }
97396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
9748028dd32a4a04154050220dd0693583d5b750330Adam Powell
975696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (flagged) {
976696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mActionItems.clear();
977696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mNonActionItems.clear();
978696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
979696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            final int itemsSize = visibleItems.size();
980696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            for (int i = 0; i < itemsSize; i++) {
981696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                MenuItemImpl item = visibleItems.get(i);
982696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                if (item.isActionButton()) {
983696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    mActionItems.add(item);
984696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                } else {
985696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    mNonActionItems.add(item);
98636fced9b211255e2137014e21fb3259042d8da85Adam Powell                }
98796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            }
988696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        } else if (mActionItems.size() + mNonActionItems.size() != getVisibleItems().size()) {
989696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            // Nobody flagged anything, but if something doesn't add up then treat everything
990696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            // as non-action items.
991696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            // (This happens during a first pass with no action-item presenters.)
992696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mActionItems.clear();
993696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mNonActionItems.clear();
994696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mNonActionItems.addAll(getVisibleItems());
99596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
99696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = false;
99796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
99896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
999696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    ArrayList<MenuItemImpl> getActionItems() {
1000696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        flagActionItems();
100196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mActionItems;
100296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
100396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
1004696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    ArrayList<MenuItemImpl> getNonActionItems() {
1005696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        flagActionItems();
100696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mNonActionItems;
100796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
100836fced9b211255e2137014e21fb3259042d8da85Adam Powell
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearHeader() {
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderIcon = null;
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderTitle = null;
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderView = null;
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Drawable icon, final View view) {
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Resources r = getResources();
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (view != null) {
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderView = view;
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If using a custom view, then the title and icon aren't used
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderTitle = null;
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderIcon = null;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (titleRes > 0) {
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderTitle = r.getText(titleRes);
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (title != null) {
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderTitle = title;
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (iconRes > 0) {
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderIcon = r.getDrawable(iconRes);
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (icon != null) {
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderIcon = icon;
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If using the title or icon, then a custom view isn't used
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderView = null;
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Notify of change
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's title. This replaces the header view. Called by the
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param title The new title.
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, title, 0, null, null);
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's title. This replaces the header view. Called by the
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param titleRes The new title (as a resource ID).
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderTitleInt(int titleRes) {
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(titleRes, null, 0, null, null);
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's icon. This replaces the header view. Called by the
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param icon The new icon.
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderIconInt(Drawable icon) {
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, 0, icon, null);
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's icon. This replaces the header view. Called by the
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param iconRes The new icon (as a resource ID).
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderIconInt(int iconRes) {
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, iconRes, null, null);
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's view. This replaces the title and icon. Called by the
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param view The new view.
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderViewInt(View view) {
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, 0, null, view);
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CharSequence getHeaderTitle() {
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderTitle;
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getHeaderIcon() {
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderIcon;
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getHeaderView() {
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderView;
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets the root menu (if this is a submenu, find its root menu).
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root menu.
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuBuilder getRootMenu() {
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the current menu info that is set on all items added to this menu
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (until this is called again with different menu info, in which case that
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one will be added to all subsequent item additions).
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuInfo The extra menu information to add.
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCurrentMenuInfo(ContextMenuInfo menuInfo) {
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurrentMenuInfo = menuInfo;
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setOptionalIconsVisible(boolean visible) {
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOptionalIconsVisible = visible;
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean getOptionalIconsVisible() {
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mOptionalIconsVisible;
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11468d02deabac62c4a68a335a7b3141795466362b89Adam Powell
11478d02deabac62c4a68a335a7b3141795466362b89Adam Powell    public boolean expandItemActionView(MenuItemImpl item) {
11488d02deabac62c4a68a335a7b3141795466362b89Adam Powell        if (mPresenters.isEmpty()) return false;
11498d02deabac62c4a68a335a7b3141795466362b89Adam Powell
11508d02deabac62c4a68a335a7b3141795466362b89Adam Powell        boolean expanded = false;
11518d02deabac62c4a68a335a7b3141795466362b89Adam Powell
11528d02deabac62c4a68a335a7b3141795466362b89Adam Powell        stopDispatchingItemsChanged();
11538d02deabac62c4a68a335a7b3141795466362b89Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
11548d02deabac62c4a68a335a7b3141795466362b89Adam Powell            final MenuPresenter presenter = ref.get();
11558d02deabac62c4a68a335a7b3141795466362b89Adam Powell            if (presenter == null) {
11568d02deabac62c4a68a335a7b3141795466362b89Adam Powell                mPresenters.remove(ref);
11578d02deabac62c4a68a335a7b3141795466362b89Adam Powell            } else if ((expanded = presenter.expandItemActionView(this, item))) {
11588d02deabac62c4a68a335a7b3141795466362b89Adam Powell                break;
11598d02deabac62c4a68a335a7b3141795466362b89Adam Powell            }
11608d02deabac62c4a68a335a7b3141795466362b89Adam Powell        }
11618d02deabac62c4a68a335a7b3141795466362b89Adam Powell        startDispatchingItemsChanged();
11628d02deabac62c4a68a335a7b3141795466362b89Adam Powell
11638d02deabac62c4a68a335a7b3141795466362b89Adam Powell        return expanded;
11648d02deabac62c4a68a335a7b3141795466362b89Adam Powell    }
11658d02deabac62c4a68a335a7b3141795466362b89Adam Powell
11668d02deabac62c4a68a335a7b3141795466362b89Adam Powell    public boolean collapseItemActionView(MenuItemImpl item) {
11678d02deabac62c4a68a335a7b3141795466362b89Adam Powell        if (mPresenters.isEmpty()) return false;
11688d02deabac62c4a68a335a7b3141795466362b89Adam Powell
11698d02deabac62c4a68a335a7b3141795466362b89Adam Powell        boolean collapsed = false;
11708d02deabac62c4a68a335a7b3141795466362b89Adam Powell
11718d02deabac62c4a68a335a7b3141795466362b89Adam Powell        stopDispatchingItemsChanged();
11728d02deabac62c4a68a335a7b3141795466362b89Adam Powell        for (WeakReference<MenuPresenter> ref : mPresenters) {
11738d02deabac62c4a68a335a7b3141795466362b89Adam Powell            final MenuPresenter presenter = ref.get();
11748d02deabac62c4a68a335a7b3141795466362b89Adam Powell            if (presenter == null) {
11758d02deabac62c4a68a335a7b3141795466362b89Adam Powell                mPresenters.remove(ref);
11768d02deabac62c4a68a335a7b3141795466362b89Adam Powell            } else if ((collapsed = presenter.collapseItemActionView(this, item))) {
11778d02deabac62c4a68a335a7b3141795466362b89Adam Powell                break;
11788d02deabac62c4a68a335a7b3141795466362b89Adam Powell            }
11798d02deabac62c4a68a335a7b3141795466362b89Adam Powell        }
11808d02deabac62c4a68a335a7b3141795466362b89Adam Powell        startDispatchingItemsChanged();
11818d02deabac62c4a68a335a7b3141795466362b89Adam Powell
11828d02deabac62c4a68a335a7b3141795466362b89Adam Powell        return collapsed;
11838d02deabac62c4a68a335a7b3141795466362b89Adam Powell    }
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1185