MenuBuilder.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextThemeWrapper;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyCharacterMap;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Menu;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MenuItem;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SubMenu;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextMenu.ContextMenuInfo;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.AdapterView;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.BaseAdapter;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Implementation of the {@link android.view.Menu} interface for creating a
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * standard menu UI.
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class MenuBuilder implements Menu {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String LOGTAG = "MenuBuilder";
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The number of different menu types */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int NUM_TYPES = 3;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The menu type that represents the icon menu view */
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_ICON = 0;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The menu type that represents the expanded menu view */
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_EXPANDED = 1;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The menu type that represents a menu dialog. Examples are context and sub
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * menus. This menu type will not have a corresponding MenuView, but it will
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have an ItemView.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_DIALOG = 2;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String VIEWS_TAG = "android:views";
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int THEME_RES_FOR_TYPE[] = new int[] {
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.style.Theme_IconMenu,
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.style.Theme_ExpandedMenu,
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0,
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int LAYOUT_RES_FOR_TYPE[] = new int[] {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.icon_menu_layout,
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.expanded_menu_layout,
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0,
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int ITEM_LAYOUT_RES_FOR_TYPE[] = new int[] {
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.icon_menu_item_layout,
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.list_menu_item_layout,
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.list_menu_item_layout,
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[]  sCategoryToOrder = new int[] {
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        1, /* No category */
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        4, /* CONTAINER */
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        5, /* SYSTEM */
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        3, /* SECONDARY */
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        2, /* ALTERNATIVE */
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0, /* SELECTED_ALTERNATIVE */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Resources mResources;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode()
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of accessing this directly.
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mQwertyMode;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the shortcuts should be visible on menus. Use isShortcutsVisible()
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of accessing this directly.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mShortcutsVisible;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Callback that will receive the various menu-related events generated by
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this class. Use getCallback to get a reference to the callback.
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Callback mCallback;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Contains all of the items for this menu */
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<MenuItemImpl> mItems;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Contains only the items that are currently visible.  This will be created/refreshed from
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getVisibleItems()} */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<MenuItemImpl> mVisibleItems;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether or not the items (or any one item's shown state) has changed since it was last
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fetched from {@link #getVisibleItems()}
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsVisibleItemsStale;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Current use case is Context Menus: As Views populate the context menu, each one has
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extra information that should be passed along.  This is the current menu info that
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should be set on all items added to this menu.
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ContextMenuInfo mCurrentMenuInfo;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header title for menu types that have a header (context and submenus) */
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CharSequence mHeaderTitle;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header icon for menu types that have a header and support icons (context) */
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Drawable mHeaderIcon;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header custom view for menu types that have a header and support custom views (context) */
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mHeaderView;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Contains the state of the View hierarchy for all menu views when the menu
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was frozen.
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SparseArray<Parcelable> mFrozenViewStates;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Prevents onItemsChanged from doing its junk, useful for batching commands
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that may individually call onItemsChanged.
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mPreventDispatchingItemsChanged = false;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mOptionalIconsVisible = false;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MenuType[] mMenuTypes;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class MenuType {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mMenuType;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The layout inflater that uses the menu type's theme */
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private LayoutInflater mInflater;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The lazily loaded {@link MenuView} */
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private WeakReference<MenuView> mMenuView;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType(int menuType) {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuType = menuType;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater getInflater() {
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Create an inflater that uses the given theme for the Views it inflates
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInflater == null) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Context wrappedContext = new ContextThemeWrapper(mContext,
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        THEME_RES_FOR_TYPE[mMenuType]);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInflater = (LayoutInflater) wrappedContext
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mInflater;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuView getMenuView(ViewGroup parent) {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (LAYOUT_RES_FOR_TYPE[mMenuType] == 0) {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MenuView menuView = mMenuView != null ? mMenuView.get() : null;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (menuView == null) {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView = (MenuView) getInflater().inflate(
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            LAYOUT_RES_FOR_TYPE[mMenuType], parent, false);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView.initialize(MenuBuilder.this, mMenuType);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Cache the view
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mMenuView = new WeakReference<MenuView>(menuView);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mFrozenViewStates != null) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        View view = (View) menuView;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        view.restoreHierarchyState(mFrozenViewStates);
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Clear this menu type's frozen state, since we just restored it
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mFrozenViewStates.remove(view.getId());
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return menuView;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasMenuView() {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mMenuView != null && mMenuView.get() != null;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by menu to notify of close and selection changes
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Callback {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a menu item is selected.
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu The menu that is the parent of the item
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param item The menu item that is selected
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return whether the menu item selection was handled
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a menu is closed.
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu The menu that was closed.
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param allMenusAreClosing Whether the menus are completely closing (true),
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            or whether there is another menu opening shortly
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            (false). For example, if the menu is closing because a
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            sub menu is about to be shown, <var>allMenusAreClosing</var>
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            is false.
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing);
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a sub menu is selected.  This is a cue to open the given sub menu's decor.
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param subMenu the sub menu that is being opened
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return whether the sub menu selection was handled by the callback
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onSubMenuSelected(SubMenuBuilder subMenu);
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a sub menu is closed
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu the sub menu that was closed
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onCloseSubMenu(SubMenuBuilder menu);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when the mode of the menu changes (for example, from icon to expanded).
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu the menu that has changed modes
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onMenuModeChange(MenuBuilder menu);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by menu items to execute their associated action
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface ItemInvoker {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean invokeItem(MenuItemImpl item);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuBuilder(Context context) {
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMenuTypes = new MenuType[NUM_TYPES];
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResources = context.getResources();
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems = new ArrayList<MenuItemImpl>();
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVisibleItems = new ArrayList<MenuItemImpl>();
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsVisibleItemsStale = true;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShortcutsVisible =
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS);
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCallback(Callback callback) {
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCallback = callback;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MenuType getMenuType(int menuType) {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mMenuTypes[menuType] == null) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuTypes[menuType] = new MenuType(menuType);
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mMenuTypes[menuType];
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets a menu View that contains this menu's items.
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuType The type of menu to get a View for (must be one of
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #TYPE_ICON}, {@link #TYPE_EXPANDED},
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #TYPE_DIALOG}).
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parent The ViewGroup that provides a set of LayoutParams values
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            for this menu view
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A View for the menu of type <var>menuType</var>
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getMenuView(int menuType, ViewGroup parent) {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The expanded menu depends on the number if items shown in the icon menu (which
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // is adjustable as setters/XML attributes on IconMenuView [imagine a larger LCD
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // wanting to show more icons]). If, for example, the activity goes through
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // an orientation change while the expanded menu is open, the icon menu's view
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // won't have an instance anymore; so here we make sure we have an icon menu view (matching
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the same parent so the layout parameters from the XML are used). This
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // will create the icon menu view and cache it (if it doesn't already exist).
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (menuType == TYPE_EXPANDED
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mMenuTypes[TYPE_ICON] == null || !mMenuTypes[TYPE_ICON].hasMenuView())) {
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            getMenuType(TYPE_ICON).getMenuView(parent);
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (View) getMenuType(menuType).getMenuView(parent);
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getNumIconMenuItemsShown() {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ViewGroup parent = null;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMenuTypes[TYPE_ICON].hasMenuView()) {
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * There isn't an icon menu view instantiated, so when we get it
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * below, it will lazily instantiate it. We should pass a proper
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * parent so it uses the layout_ attributes present in the XML
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * layout file.
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuTypes[TYPE_EXPANDED].hasMenuView()) {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                View expandedMenuView = (View) mMenuTypes[TYPE_EXPANDED].getMenuView(null);
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parent = (ViewGroup) expandedMenuView.getParent();
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ((IconMenuView) getMenuView(TYPE_ICON, parent)).getNumActualItemsShown();
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clears the cached menu views. Call this if the menu views need to another
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * layout (for example, if the screen size has changed).
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearMenuViews() {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuTypes[i] != null) {
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMenuTypes[i].mMenuView = null;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = mItems.size() - 1; i >= 0; i--) {
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((SubMenuBuilder) item.getSubMenu()).clearMenuViews();
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.clearItemViews();
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Adds an item to the menu.  The other add methods funnel to this.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int ordering = getOrdering(categoryOrder);
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder, ordering, title);
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrentMenuInfo != null) {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Pass along the current menu info
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.setMenuInfo(mCurrentMenuInfo);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.add(findInsertIndex(mItems, ordering), item);
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return item;
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(CharSequence title) {
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(0, 0, 0, title);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int titleRes) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(0, 0, 0, mResources.getString(titleRes));
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(group, id, categoryOrder, title);
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int group, int id, int categoryOrder, int title) {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(group, id, categoryOrder, mResources.getString(title));
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(CharSequence title) {
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(0, 0, 0, title);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int titleRes) {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        item.setSubMenu(subMenu);
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return subMenu;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PackageManager pm = mContext.getPackageManager();
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final List<ResolveInfo> lri =
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = lri != null ? lri.size() : 0;
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            removeGroup(group);
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ResolveInfo ri = lri.get(i);
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent rintent = new Intent(
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rintent.setComponent(new ComponentName(
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.applicationInfo.packageName,
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.name));
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .setIcon(ri.loadIcon(pm))
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .setIntent(rintent);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outSpecificItems != null && ri.specificIndex >= 0) {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outSpecificItems[ri.specificIndex] = item;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return N;
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeItem(int id) {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeItemAtInt(findItemIndex(id), true);
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGroup(int group) {
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int i = findGroupIndex(group);
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i >= 0) {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int maxRemovable = mItems.size() - i;
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int numRemoved = 0;
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't force update for each one, this method will do it at the end
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeItemAtInt(i, false);
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Notify menu views
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onItemsChanged(false);
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove the item at the given index and optionally forces menu views to
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * update.
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param index The index of the item to be removed. If this index is
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            invalid an exception is thrown.
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param updateChildrenOnMenuViews Whether to force update on menu views.
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            Please make sure you eventually call this after your batch of
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            removals.
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((index < 0) || (index >= mItems.size())) return;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.remove(index);
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (updateChildrenOnMenuViews) onItemsChanged(false);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeItemAt(int index) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeItemAtInt(index, true);
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearAll() {
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreventDispatchingItemsChanged = true;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clear();
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clearHeader();
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreventDispatchingItemsChanged = false;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(true);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clear() {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.clear();
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(true);
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setExclusiveItemChecked(MenuItem item) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int group = item.getGroupId();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl curItem = mItems.get(i);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (curItem.getGroupId() == group) {
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!curItem.isExclusiveCheckable()) continue;
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!curItem.isCheckable()) continue;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check the item meant to be checked, uncheck the others (that are in the group)
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curItem.setCheckedInt(curItem == item);
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setExclusiveCheckable(exclusive);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setCheckable(checkable);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupVisible(int group, boolean visible) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // than setVisible and at the end notify of items being changed
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changedAtLeastOneItem = false;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (changedAtLeastOneItem) onItemsChanged(false);
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupEnabled(int group, boolean enabled) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setEnabled(enabled);
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasVisibleItems() {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.isVisible()) {
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem findItem(int id) {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getItemId() == id) {
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return item;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (item.hasSubMenu()) {
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MenuItem possibleItem = item.getSubMenu().findItem(id);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (possibleItem != null) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return possibleItem;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findItemIndex(int id) {
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getItemId() == id) {
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i;
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findGroupIndex(int group) {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return findGroupIndex(group, 0);
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findGroupIndex(int group, int start) {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (start < 0) {
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            start = 0;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = start; i < size; i++) {
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final MenuItemImpl item = mItems.get(i);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int size() {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mItems.size();
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** {@inheritDoc} */
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem getItem(int index) {
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mItems.get(index);
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShortcutKey(int keyCode, KeyEvent event) {
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return findItemWithShortcutForKey(keyCode, event) != null;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setQwertyMode(boolean isQwerty) {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyMode = isQwerty;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        refreshShortcuts(isShortcutsVisible(), isQwerty);
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the ordering across all items. This will grab the category from
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the upper bits, find out how to order the category with respect to other
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * categories, and combine it with the lower bits.
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param categoryOrder The category order for a particular item (if it has
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            not been or/add with a category, the default category is
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            assumed).
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return An ordering integer that can be used to order this item across
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         all the items (even from other categories).
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int getOrdering(int categoryOrder)
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index < 0 || index >= sCategoryToOrder.length) {
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("order does not contain a valid category.");
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return whether the menu shortcuts are in qwerty mode or not
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean isQwertyMode() {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mQwertyMode;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Refreshes the shortcut labels on each of the displayed items.  Passes the arguments
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * so submenus don't need to call their parent menu for the same values.
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void refreshShortcuts(boolean shortcutsVisible, boolean qwertyMode) {
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl item;
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = mItems.size() - 1; i >= 0; i--) {
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item = mItems.get(i);
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((MenuBuilder) item.getSubMenu()).refreshShortcuts(shortcutsVisible, qwertyMode);
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.refreshShortcutOnItemViews(shortcutsVisible, qwertyMode);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets whether the shortcuts should be visible on menus.  Devices without hardware
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * key input will never make shortcuts visible even if this method is passed 'true'.
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param shortcutsVisible Whether shortcuts should be visible (if true and a
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            menu item does not have a shortcut defined, that item will
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            still NOT show a shortcut)
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setShortcutsVisible(boolean shortcutsVisible) {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShortcutsVisible == shortcutsVisible) return;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShortcutsVisible =
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS)
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && shortcutsVisible;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        refreshShortcuts(mShortcutsVisible, isQwertyMode());
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Whether shortcuts should be visible on menus.
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShortcutsVisible() {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mShortcutsVisible;
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Resources getResources() {
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mResources;
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Callback getCallback() {
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCallback;
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = items.size() - 1; i >= 0; i--) {
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = items.get(i);
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getOrdering() <= ordering) {
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i + 1;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean handled = false;
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (item != null) {
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handled = performItemAction(item, flags);
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(true);
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return handled;
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean qwerty = isQwertyMode();
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int metaState = event.getMetaState();
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get the chars associated with the keyCode (i.e using any chording combo)
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The delete key is not mapped to '\b' so we treat it specially
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Look for an item whose shortcut is this key.
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MenuItemImpl subMenuItem = ((MenuBuilder)item.getSubMenu())
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                .findItemWithShortcutForKey(keyCode, event);
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (subMenuItem != null) {
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return subMenuItem;
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (qwerty) {
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final char shortcutAlphaChar = item.getAlphabeticShortcut();
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        (shortcutAlphaChar != 0) &&
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        (shortcutAlphaChar == possibleChars.meta[0]
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         || shortcutAlphaChar == possibleChars.meta[2]
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         || (shortcutAlphaChar == '\b' && keyCode == KeyEvent.KEYCODE_DEL)) &&
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        item.isEnabled()) {
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return item;
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final char shortcutNumericChar = item.getNumericShortcut();
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        (shortcutNumericChar != 0) &&
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        (shortcutNumericChar == possibleChars.meta[0]
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            || shortcutNumericChar == possibleChars.meta[2]) &&
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        item.isEnabled()) {
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return item;
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performIdentifierAction(int id, int flags) {
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Look for an item whose identifier is the id.
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return performItemAction(findItem(id), flags);
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performItemAction(MenuItem item, int flags) {
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl itemImpl = (MenuItemImpl) item;
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (itemImpl == null || !itemImpl.isEnabled()) {
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean invoked = itemImpl.invoke();
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (item.hasSubMenu()) {
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(false);
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCallback != null) {
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Return true if the sub menu was invoked or the item was invoked previously
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                invoked = mCallback.onSubMenuSelected((SubMenuBuilder) item.getSubMenu())
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || invoked;
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                close(true);
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return invoked;
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Closes the visible menu.
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param allMenusAreClosing Whether the menus are completely closing (true),
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            or whether there is another menu coming in this menu's place
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            (false). For example, if the menu is closing because a
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            sub menu is about to be shown, <var>allMenusAreClosing</var>
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            is false.
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void close(boolean allMenusAreClosing) {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Callback callback = getCallback();
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (callback != null) {
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            callback.onCloseMenu(this, allMenusAreClosing);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** {@inheritDoc} */
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void close() {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close(true);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when an item is added or removed.
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cleared Whether the items were cleared or just changed.
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void onItemsChanged(boolean cleared) {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mPreventDispatchingItemsChanged) {
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsVisibleItemsStale == false) mIsVisibleItemsStale = true;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuType[] menuTypes = mMenuTypes;
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < NUM_TYPES; i++) {
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((menuTypes[i] != null) && (menuTypes[i].hasMenuView())) {
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MenuView menuView = menuTypes[i].mMenuView.get();
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView.updateChildren(cleared);
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by {@link MenuItemImpl} when its visible flag is changed.
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param item The item that has gone through a visibility change.
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void onItemVisibleChanged(MenuItemImpl item) {
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Notify of items being changed
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<MenuItemImpl> getVisibleItems() {
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mIsVisibleItemsStale) return mVisibleItems;
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Refresh the visible items
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVisibleItems.clear();
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int itemsSize = mItems.size();
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl item;
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < itemsSize; i++) {
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item = mItems.get(i);
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.isVisible()) mVisibleItems.add(item);
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsVisibleItemsStale = false;
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mVisibleItems;
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearHeader() {
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderIcon = null;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderTitle = null;
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderView = null;
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Drawable icon, final View view) {
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Resources r = getResources();
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (view != null) {
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderView = view;
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If using a custom view, then the title and icon aren't used
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderTitle = null;
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderIcon = null;
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (titleRes > 0) {
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderTitle = r.getText(titleRes);
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (title != null) {
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderTitle = title;
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (iconRes > 0) {
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderIcon = r.getDrawable(iconRes);
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (icon != null) {
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderIcon = icon;
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If using the title or icon, then a custom view isn't used
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderView = null;
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Notify of change
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's title. This replaces the header view. Called by the
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param title The new title.
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, title, 0, null, null);
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's title. This replaces the header view. Called by the
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param titleRes The new title (as a resource ID).
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderTitleInt(int titleRes) {
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(titleRes, null, 0, null, null);
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's icon. This replaces the header view. Called by the
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param icon The new icon.
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderIconInt(Drawable icon) {
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, 0, icon, null);
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's icon. This replaces the header view. Called by the
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param iconRes The new icon (as a resource ID).
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderIconInt(int iconRes) {
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, iconRes, null, null);
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's view. This replaces the title and icon. Called by the
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param view The new view.
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderViewInt(View view) {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, 0, null, view);
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CharSequence getHeaderTitle() {
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderTitle;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getHeaderIcon() {
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderIcon;
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getHeaderView() {
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderView;
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets the root menu (if this is a submenu, find its root menu).
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root menu.
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuBuilder getRootMenu() {
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the current menu info that is set on all items added to this menu
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (until this is called again with different menu info, in which case that
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one will be added to all subsequent item additions).
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuInfo The extra menu information to add.
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCurrentMenuInfo(ContextMenuInfo menuInfo) {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurrentMenuInfo = menuInfo;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets an adapter for providing items and their views.
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuType The type of menu to get an adapter for.
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A {@link MenuAdapter} for this menu with the given menu type.
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuAdapter getMenuAdapter(int menuType) {
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new MenuAdapter(menuType);
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setOptionalIconsVisible(boolean visible) {
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOptionalIconsVisible = visible;
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean getOptionalIconsVisible() {
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mOptionalIconsVisible;
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void saveHierarchyState(Bundle outState) {
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SparseArray<Parcelable> viewStates = new SparseArray<Parcelable>();
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType[] menuTypes = mMenuTypes;
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i] == null) {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i].hasMenuView()) {
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((View) menuTypes[i].getMenuView(null)).saveHierarchyState(viewStates);
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        outState.putSparseParcelableArray(VIEWS_TAG, viewStates);
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void restoreHierarchyState(Bundle inState) {
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Save this for menu views opened later
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SparseArray<Parcelable> viewStates = mFrozenViewStates = inState
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getSparseParcelableArray(VIEWS_TAG);
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Thaw those menu views already open
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType[] menuTypes = mMenuTypes;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i] == null) {
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i].hasMenuView()) {
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((View) menuTypes[i].getMenuView(null)).restoreHierarchyState(viewStates);
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * An adapter that allows an {@link AdapterView} to use this {@link MenuBuilder} as a data
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * source.  This adapter will use only the visible/shown items from the menu.
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class MenuAdapter extends BaseAdapter {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mMenuType;
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public MenuAdapter(int menuType) {
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuType = menuType;
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getOffset() {
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuType == TYPE_EXPANDED) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getNumIconMenuItemsShown();
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getCount() {
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getVisibleItems().size() - getOffset();
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public MenuItemImpl getItem(int position) {
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getVisibleItems().get(position + getOffset());
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public long getItemId(int position) {
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Since a menu item's ID is optional, we'll use the position as an
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ID for the item in the AdapterView
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return position;
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View getView(int position, View convertView, ViewGroup parent) {
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ((MenuItemImpl) getItem(position)).getItemView(mMenuType, parent);
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1121