MenuBuilder.java revision 8028dd32a4a04154050220dd0693583d5b750330
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;
3096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport android.util.Log;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextThemeWrapper;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyCharacterMap;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
3596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport android.view.LayoutInflater;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Menu;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MenuItem;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SubMenu;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextMenu.ContextMenuInfo;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.AdapterView;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.BaseAdapter;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
48e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roardimport java.util.Vector;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Implementation of the {@link android.view.Menu} interface for creating a
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * standard menu UI.
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class MenuBuilder implements Menu {
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String LOGTAG = "MenuBuilder";
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The number of different menu types */
584267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public static final int NUM_TYPES = 5;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The menu type that represents the icon menu view */
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_ICON = 0;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The menu type that represents the expanded menu view */
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_EXPANDED = 1;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The menu type that represents a menu dialog. Examples are context and sub
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * menus. This menu type will not have a corresponding MenuView, but it will
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have an ItemView.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_DIALOG = 2;
6996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
7096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * The menu type that represents a button in the application's action bar.
7196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
7296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public static final int TYPE_ACTION_BUTTON = 3;
734267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    /**
744267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     * The menu type that represents a menu popup.
754267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     */
764267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public static final int TYPE_POPUP = 4;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String VIEWS_TAG = "android:views";
794267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int THEME_RES_FOR_TYPE[] = new int[] {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.style.Theme_IconMenu,
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.style.Theme_ExpandedMenu,
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0,
8596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        0,
864267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        0,
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int LAYOUT_RES_FOR_TYPE[] = new int[] {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.icon_menu_layout,
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.expanded_menu_layout,
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0,
9496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        com.android.internal.R.layout.action_menu_layout,
954267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        0,
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int ITEM_LAYOUT_RES_FOR_TYPE[] = new int[] {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.icon_menu_item_layout,
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.list_menu_item_layout,
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.list_menu_item_layout,
10396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        com.android.internal.R.layout.action_menu_item_layout,
1044267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        com.android.internal.R.layout.list_menu_item_layout,
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[]  sCategoryToOrder = new int[] {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        1, /* No category */
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        4, /* CONTAINER */
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        5, /* SYSTEM */
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        3, /* SECONDARY */
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        2, /* ALTERNATIVE */
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0, /* SELECTED_ALTERNATIVE */
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Resources mResources;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode()
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of accessing this directly.
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mQwertyMode;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the shortcuts should be visible on menus. Use isShortcutsVisible()
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of accessing this directly.
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mShortcutsVisible;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Callback that will receive the various menu-related events generated by
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this class. Use getCallback to get a reference to the callback.
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Callback mCallback;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Contains all of the items for this menu */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<MenuItemImpl> mItems;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Contains only the items that are currently visible.  This will be created/refreshed from
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getVisibleItems()} */
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<MenuItemImpl> mVisibleItems;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether or not the items (or any one item's shown state) has changed since it was last
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fetched from {@link #getVisibleItems()}
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsVisibleItemsStale;
14896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
14996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
15096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Contains only the items that should appear in the Action Bar, if present.
15196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
15296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private ArrayList<MenuItemImpl> mActionItems;
15396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
15496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Contains items that should NOT appear in the Action Bar, if present.
15596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
15696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private ArrayList<MenuItemImpl> mNonActionItems;
15796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
15896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * The number of visible action buttons permitted in this menu
15996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
16096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private int mMaxActionItems;
16196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
16296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Whether or not the items (or any one item's action state) has changed since it was
16396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * last fetched.
16496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
16596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private boolean mIsActionItemsStale;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1688028dd32a4a04154050220dd0693583d5b750330Adam Powell     * Whether the process of granting space as action items should reserve a space for
1698028dd32a4a04154050220dd0693583d5b750330Adam Powell     * an overflow option in the action list.
1708028dd32a4a04154050220dd0693583d5b750330Adam Powell     */
1718028dd32a4a04154050220dd0693583d5b750330Adam Powell    private boolean mReserveActionOverflow;
1728028dd32a4a04154050220dd0693583d5b750330Adam Powell
1738028dd32a4a04154050220dd0693583d5b750330Adam Powell    /**
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Current use case is Context Menus: As Views populate the context menu, each one has
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extra information that should be passed along.  This is the current menu info that
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should be set on all items added to this menu.
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ContextMenuInfo mCurrentMenuInfo;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header title for menu types that have a header (context and submenus) */
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CharSequence mHeaderTitle;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header icon for menu types that have a header and support icons (context) */
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Drawable mHeaderIcon;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header custom view for menu types that have a header and support custom views (context) */
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mHeaderView;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Contains the state of the View hierarchy for all menu views when the menu
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was frozen.
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SparseArray<Parcelable> mFrozenViewStates;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Prevents onItemsChanged from doing its junk, useful for batching commands
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that may individually call onItemsChanged.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mPreventDispatchingItemsChanged = false;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mOptionalIconsVisible = false;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MenuType[] mMenuTypes;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class MenuType {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mMenuType;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The layout inflater that uses the menu type's theme */
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private LayoutInflater mInflater;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The lazily loaded {@link MenuView} */
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private WeakReference<MenuView> mMenuView;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType(int menuType) {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuType = menuType;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater getInflater() {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Create an inflater that uses the given theme for the Views it inflates
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInflater == null) {
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Context wrappedContext = new ContextThemeWrapper(mContext,
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        THEME_RES_FOR_TYPE[mMenuType]);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInflater = (LayoutInflater) wrappedContext
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mInflater;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuView getMenuView(ViewGroup parent) {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (LAYOUT_RES_FOR_TYPE[mMenuType] == 0) {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MenuView menuView = mMenuView != null ? mMenuView.get() : null;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (menuView == null) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView = (MenuView) getInflater().inflate(
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            LAYOUT_RES_FOR_TYPE[mMenuType], parent, false);
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView.initialize(MenuBuilder.this, mMenuType);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Cache the view
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mMenuView = new WeakReference<MenuView>(menuView);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mFrozenViewStates != null) {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        View view = (View) menuView;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        view.restoreHierarchyState(mFrozenViewStates);
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Clear this menu type's frozen state, since we just restored it
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mFrozenViewStates.remove(view.getId());
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return menuView;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasMenuView() {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mMenuView != null && mMenuView.get() != null;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by menu to notify of close and selection changes
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Callback {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a menu item is selected.
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu The menu that is the parent of the item
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param item The menu item that is selected
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return whether the menu item selection was handled
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a menu is closed.
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu The menu that was closed.
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param allMenusAreClosing Whether the menus are completely closing (true),
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            or whether there is another menu opening shortly
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            (false). For example, if the menu is closing because a
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            sub menu is about to be shown, <var>allMenusAreClosing</var>
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            is false.
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a sub menu is selected.  This is a cue to open the given sub menu's decor.
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param subMenu the sub menu that is being opened
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return whether the sub menu selection was handled by the callback
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onSubMenuSelected(SubMenuBuilder subMenu);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a sub menu is closed
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu the sub menu that was closed
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onCloseSubMenu(SubMenuBuilder menu);
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when the mode of the menu changes (for example, from icon to expanded).
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu the menu that has changed modes
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onMenuModeChange(MenuBuilder menu);
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by menu items to execute their associated action
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface ItemInvoker {
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean invokeItem(MenuItemImpl item);
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuBuilder(Context context) {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMenuTypes = new MenuType[NUM_TYPES];
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResources = context.getResources();
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems = new ArrayList<MenuItemImpl>();
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVisibleItems = new ArrayList<MenuItemImpl>();
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsVisibleItemsStale = true;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
32396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mActionItems = new ArrayList<MenuItemImpl>();
32496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mNonActionItems = new ArrayList<MenuItemImpl>();
32596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = true;
32696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShortcutsVisible =
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS);
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCallback(Callback callback) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCallback = callback;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MenuType getMenuType(int menuType) {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mMenuTypes[menuType] == null) {
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuTypes[menuType] = new MenuType(menuType);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mMenuTypes[menuType];
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets a menu View that contains this menu's items.
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuType The type of menu to get a View for (must be one of
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #TYPE_ICON}, {@link #TYPE_EXPANDED},
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #TYPE_DIALOG}).
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parent The ViewGroup that provides a set of LayoutParams values
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            for this menu view
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A View for the menu of type <var>menuType</var>
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getMenuView(int menuType, ViewGroup parent) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The expanded menu depends on the number if items shown in the icon menu (which
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // is adjustable as setters/XML attributes on IconMenuView [imagine a larger LCD
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // wanting to show more icons]). If, for example, the activity goes through
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // an orientation change while the expanded menu is open, the icon menu's view
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // won't have an instance anymore; so here we make sure we have an icon menu view (matching
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the same parent so the layout parameters from the XML are used). This
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // will create the icon menu view and cache it (if it doesn't already exist).
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (menuType == TYPE_EXPANDED
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mMenuTypes[TYPE_ICON] == null || !mMenuTypes[TYPE_ICON].hasMenuView())) {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            getMenuType(TYPE_ICON).getMenuView(parent);
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (View) getMenuType(menuType).getMenuView(parent);
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getNumIconMenuItemsShown() {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ViewGroup parent = null;
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMenuTypes[TYPE_ICON].hasMenuView()) {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * There isn't an icon menu view instantiated, so when we get it
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * below, it will lazily instantiate it. We should pass a proper
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * parent so it uses the layout_ attributes present in the XML
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * layout file.
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuTypes[TYPE_EXPANDED].hasMenuView()) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                View expandedMenuView = (View) mMenuTypes[TYPE_EXPANDED].getMenuView(null);
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parent = (ViewGroup) expandedMenuView.getParent();
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ((IconMenuView) getMenuView(TYPE_ICON, parent)).getNumActualItemsShown();
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clears the cached menu views. Call this if the menu views need to another
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * layout (for example, if the screen size has changed).
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearMenuViews() {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuTypes[i] != null) {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMenuTypes[i].mMenuView = null;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = mItems.size() - 1; i >= 0; i--) {
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((SubMenuBuilder) item.getSubMenu()).clearMenuViews();
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.clearItemViews();
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Adds an item to the menu.  The other add methods funnel to this.
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int ordering = getOrdering(categoryOrder);
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder, ordering, title);
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrentMenuInfo != null) {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Pass along the current menu info
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.setMenuInfo(mCurrentMenuInfo);
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.add(findInsertIndex(mItems, ordering), item);
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return item;
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(CharSequence title) {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(0, 0, 0, title);
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int titleRes) {
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(0, 0, 0, mResources.getString(titleRes));
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(group, id, categoryOrder, title);
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int group, int id, int categoryOrder, int title) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(group, id, categoryOrder, mResources.getString(title));
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(CharSequence title) {
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(0, 0, 0, title);
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int titleRes) {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        item.setSubMenu(subMenu);
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return subMenu;
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PackageManager pm = mContext.getPackageManager();
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final List<ResolveInfo> lri =
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = lri != null ? lri.size() : 0;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            removeGroup(group);
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ResolveInfo ri = lri.get(i);
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent rintent = new Intent(
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rintent.setComponent(new ComponentName(
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.applicationInfo.packageName,
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.name));
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .setIcon(ri.loadIcon(pm))
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .setIntent(rintent);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outSpecificItems != null && ri.specificIndex >= 0) {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outSpecificItems[ri.specificIndex] = item;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return N;
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeItem(int id) {
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeItemAtInt(findItemIndex(id), true);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGroup(int group) {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int i = findGroupIndex(group);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i >= 0) {
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int maxRemovable = mItems.size() - i;
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int numRemoved = 0;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't force update for each one, this method will do it at the end
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeItemAtInt(i, false);
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Notify menu views
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onItemsChanged(false);
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove the item at the given index and optionally forces menu views to
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * update.
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param index The index of the item to be removed. If this index is
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            invalid an exception is thrown.
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param updateChildrenOnMenuViews Whether to force update on menu views.
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            Please make sure you eventually call this after your batch of
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            removals.
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((index < 0) || (index >= mItems.size())) return;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.remove(index);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (updateChildrenOnMenuViews) onItemsChanged(false);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeItemAt(int index) {
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeItemAtInt(index, true);
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearAll() {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreventDispatchingItemsChanged = true;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clear();
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clearHeader();
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreventDispatchingItemsChanged = false;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(true);
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clear() {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.clear();
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(true);
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setExclusiveItemChecked(MenuItem item) {
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int group = item.getGroupId();
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl curItem = mItems.get(i);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (curItem.getGroupId() == group) {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!curItem.isExclusiveCheckable()) continue;
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!curItem.isCheckable()) continue;
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check the item meant to be checked, uncheck the others (that are in the group)
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curItem.setCheckedInt(curItem == item);
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setExclusiveCheckable(exclusive);
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setCheckable(checkable);
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupVisible(int group, boolean visible) {
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // than setVisible and at the end notify of items being changed
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changedAtLeastOneItem = false;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (changedAtLeastOneItem) onItemsChanged(false);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupEnabled(int group, boolean enabled) {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setEnabled(enabled);
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasVisibleItems() {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.isVisible()) {
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem findItem(int id) {
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getItemId() == id) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return item;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (item.hasSubMenu()) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MenuItem possibleItem = item.getSubMenu().findItem(id);
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (possibleItem != null) {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return possibleItem;
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findItemIndex(int id) {
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getItemId() == id) {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i;
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findGroupIndex(int group) {
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return findGroupIndex(group, 0);
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findGroupIndex(int group, int start) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (start < 0) {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            start = 0;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = start; i < size; i++) {
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final MenuItemImpl item = mItems.get(i);
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i;
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int size() {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mItems.size();
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** {@inheritDoc} */
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem getItem(int index) {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mItems.get(index);
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6798028dd32a4a04154050220dd0693583d5b750330Adam Powell    public MenuItem getOverflowItem(int index) {
6808028dd32a4a04154050220dd0693583d5b750330Adam Powell        flagActionItems(true);
6818028dd32a4a04154050220dd0693583d5b750330Adam Powell        return mNonActionItems.get(index);
6828028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
6838028dd32a4a04154050220dd0693583d5b750330Adam Powell
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShortcutKey(int keyCode, KeyEvent event) {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return findItemWithShortcutForKey(keyCode, event) != null;
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setQwertyMode(boolean isQwerty) {
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyMode = isQwerty;
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        refreshShortcuts(isShortcutsVisible(), isQwerty);
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the ordering across all items. This will grab the category from
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the upper bits, find out how to order the category with respect to other
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * categories, and combine it with the lower bits.
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param categoryOrder The category order for a particular item (if it has
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            not been or/add with a category, the default category is
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            assumed).
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return An ordering integer that can be used to order this item across
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         all the items (even from other categories).
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int getOrdering(int categoryOrder)
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index < 0 || index >= sCategoryToOrder.length) {
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("order does not contain a valid category.");
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return whether the menu shortcuts are in qwerty mode or not
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean isQwertyMode() {
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mQwertyMode;
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Refreshes the shortcut labels on each of the displayed items.  Passes the arguments
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * so submenus don't need to call their parent menu for the same values.
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void refreshShortcuts(boolean shortcutsVisible, boolean qwertyMode) {
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl item;
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = mItems.size() - 1; i >= 0; i--) {
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item = mItems.get(i);
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((MenuBuilder) item.getSubMenu()).refreshShortcuts(shortcutsVisible, qwertyMode);
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.refreshShortcutOnItemViews(shortcutsVisible, qwertyMode);
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets whether the shortcuts should be visible on menus.  Devices without hardware
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * key input will never make shortcuts visible even if this method is passed 'true'.
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param shortcutsVisible Whether shortcuts should be visible (if true and a
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            menu item does not have a shortcut defined, that item will
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            still NOT show a shortcut)
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setShortcutsVisible(boolean shortcutsVisible) {
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShortcutsVisible == shortcutsVisible) return;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShortcutsVisible =
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS)
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && shortcutsVisible;
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        refreshShortcuts(mShortcutsVisible, isQwertyMode());
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Whether shortcuts should be visible on menus.
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShortcutsVisible() {
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mShortcutsVisible;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Resources getResources() {
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mResources;
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Callback getCallback() {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCallback;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = items.size() - 1; i >= 0; i--) {
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = items.get(i);
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getOrdering() <= ordering) {
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i + 1;
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean handled = false;
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (item != null) {
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handled = performItemAction(item, flags);
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(true);
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return handled;
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
804e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    /*
805e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * This function will return all the menu and sub-menu items that can
806e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * be directly (the shortcut directly corresponds) and indirectly
807e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * (the ALT-enabled char corresponds to the shortcut) associated
808e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * with the keyCode.
809e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     */
810e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    List<MenuItemImpl> findItemsWithShortcutForKey(int keyCode, KeyEvent event) {
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean qwerty = isQwertyMode();
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int metaState = event.getMetaState();
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get the chars associated with the keyCode (i.e using any chording combo)
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The delete key is not mapped to '\b' so we treat it specially
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
821e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        Vector<MenuItemImpl> items = new Vector();
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Look for an item whose shortcut is this key.
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
827e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                List<MenuItemImpl> subMenuItems = ((MenuBuilder)item.getSubMenu())
828e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    .findItemsWithShortcutForKey(keyCode, event);
829e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                items.addAll(subMenuItems);
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
831e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
832e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
833e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  (shortcutChar != 0) &&
834e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  (shortcutChar == possibleChars.meta[0]
835e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                      || shortcutChar == possibleChars.meta[2]
836e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                      || (qwerty && shortcutChar == '\b' &&
837e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                          keyCode == KeyEvent.KEYCODE_DEL)) &&
838e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  item.isEnabled()) {
839e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                items.add(item);
840e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            }
841e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
842e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        return items;
843e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    }
844e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
845e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    /*
846e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * We want to return the menu item associated with the key, but if there is no
847e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * ambiguity (i.e. there is only one menu item corresponding to the key) we want
848e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * to return it even if it's not an exact match; this allow the user to
849e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * _not_ use the ALT key for example, making the use of shortcuts slightly more
850e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
851e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
852e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     *
853e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * On the other hand, if two (or more) shortcuts corresponds to the same key,
854e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * we have to only return the exact match.
855e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     */
856e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
857e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // Get all items that can be associated directly or indirectly with the keyCode
858e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        List<MenuItemImpl> items = findItemsWithShortcutForKey(keyCode, event);
859e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
860e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        if (items == null) {
861e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            return null;
862e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
863e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
864e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final int metaState = event.getMetaState();
865e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
866e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // Get the chars associated with the keyCode (i.e using any chording combo)
867e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        event.getKeyData(possibleChars);
868e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
869e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // If we have only one element, we can safely returns it
870e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        if (items.size() == 1) {
871e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            return items.get(0);
872e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
873e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
874e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final boolean qwerty = isQwertyMode();
875e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // If we found more than one item associated with the key,
876e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // we have to return the exact match
877e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        for (MenuItemImpl item : items) {
878e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
879e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            if ((shortcutChar == possibleChars.meta[0] &&
880e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    (metaState & KeyEvent.META_ALT_ON) == 0)
881e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                || (shortcutChar == possibleChars.meta[2] &&
882e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    (metaState & KeyEvent.META_ALT_ON) != 0)
883e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                || (qwerty && shortcutChar == '\b' &&
884e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    keyCode == KeyEvent.KEYCODE_DEL)) {
885e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                return item;
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
890e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performIdentifierAction(int id, int flags) {
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Look for an item whose identifier is the id.
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return performItemAction(findItem(id), flags);
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performItemAction(MenuItem item, int flags) {
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl itemImpl = (MenuItemImpl) item;
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (itemImpl == null || !itemImpl.isEnabled()) {
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean invoked = itemImpl.invoke();
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (item.hasSubMenu()) {
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(false);
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCallback != null) {
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Return true if the sub menu was invoked or the item was invoked previously
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                invoked = mCallback.onSubMenuSelected((SubMenuBuilder) item.getSubMenu())
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || invoked;
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                close(true);
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return invoked;
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Closes the visible menu.
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param allMenusAreClosing Whether the menus are completely closing (true),
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            or whether there is another menu coming in this menu's place
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            (false). For example, if the menu is closing because a
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            sub menu is about to be shown, <var>allMenusAreClosing</var>
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            is false.
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void close(boolean allMenusAreClosing) {
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Callback callback = getCallback();
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (callback != null) {
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            callback.onCloseMenu(this, allMenusAreClosing);
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** {@inheritDoc} */
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void close() {
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close(true);
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when an item is added or removed.
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cleared Whether the items were cleared or just changed.
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void onItemsChanged(boolean cleared) {
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mPreventDispatchingItemsChanged) {
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsVisibleItemsStale == false) mIsVisibleItemsStale = true;
95196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            if (mIsActionItemsStale == false) mIsActionItemsStale = true;
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuType[] menuTypes = mMenuTypes;
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < NUM_TYPES; i++) {
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((menuTypes[i] != null) && (menuTypes[i].hasMenuView())) {
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MenuView menuView = menuTypes[i].mMenuView.get();
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView.updateChildren(cleared);
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by {@link MenuItemImpl} when its visible flag is changed.
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param item The item that has gone through a visibility change.
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void onItemVisibleChanged(MenuItemImpl item) {
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Notify of items being changed
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
97296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
97396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Called by {@link MenuItemImpl} when its action request status is changed.
97496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * @param item The item that has gone through a change in action request status.
97596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
97696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    void onItemActionRequestChanged(MenuItemImpl item) {
97796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        // Notify of items being changed
97896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        onItemsChanged(false);
97996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
98096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<MenuItemImpl> getVisibleItems() {
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mIsVisibleItemsStale) return mVisibleItems;
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Refresh the visible items
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVisibleItems.clear();
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int itemsSize = mItems.size();
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl item;
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < itemsSize; i++) {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item = mItems.get(i);
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.isVisible()) mVisibleItems.add(item);
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsVisibleItemsStale = false;
99596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = true;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mVisibleItems;
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
99996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
10008028dd32a4a04154050220dd0693583d5b750330Adam Powell    private void flagActionItems(boolean reserveActionOverflow) {
10018028dd32a4a04154050220dd0693583d5b750330Adam Powell        if (reserveActionOverflow != mReserveActionOverflow) {
10028028dd32a4a04154050220dd0693583d5b750330Adam Powell            mReserveActionOverflow = reserveActionOverflow;
10038028dd32a4a04154050220dd0693583d5b750330Adam Powell            mIsActionItemsStale = true;
10048028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
10058028dd32a4a04154050220dd0693583d5b750330Adam Powell
100696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        if (!mIsActionItemsStale) {
100796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            return;
100896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
10098028dd32a4a04154050220dd0693583d5b750330Adam Powell
101096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        final ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
101196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        final int itemsSize = visibleItems.size();
101296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        int maxActions = mMaxActionItems;
10138028dd32a4a04154050220dd0693583d5b750330Adam Powell
10148028dd32a4a04154050220dd0693583d5b750330Adam Powell        int requiredItems = 0;
10158028dd32a4a04154050220dd0693583d5b750330Adam Powell        int requestedItems = 0;
10168028dd32a4a04154050220dd0693583d5b750330Adam Powell        boolean hasOverflow = false;
101796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        for (int i = 0; i < itemsSize; i++) {
101896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            MenuItemImpl item = visibleItems.get(i);
101996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            if (item.requiresActionButton()) {
10208028dd32a4a04154050220dd0693583d5b750330Adam Powell                requiredItems++;
10218028dd32a4a04154050220dd0693583d5b750330Adam Powell            } else if (item.requestsActionButton()) {
10228028dd32a4a04154050220dd0693583d5b750330Adam Powell                requestedItems++;
10238028dd32a4a04154050220dd0693583d5b750330Adam Powell            } else {
10248028dd32a4a04154050220dd0693583d5b750330Adam Powell                hasOverflow = true;
102596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            }
102696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
10278028dd32a4a04154050220dd0693583d5b750330Adam Powell
10288028dd32a4a04154050220dd0693583d5b750330Adam Powell        // Reserve a spot for the overflow item if needed.
10298028dd32a4a04154050220dd0693583d5b750330Adam Powell        if (reserveActionOverflow &&
10308028dd32a4a04154050220dd0693583d5b750330Adam Powell                (hasOverflow || requiredItems + requestedItems > maxActions)) {
10318028dd32a4a04154050220dd0693583d5b750330Adam Powell            maxActions--;
10328028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
10338028dd32a4a04154050220dd0693583d5b750330Adam Powell        maxActions -= requiredItems;
10348028dd32a4a04154050220dd0693583d5b750330Adam Powell
103596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        // Flag as many more requested items as will fit.
103696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        for (int i = 0; i < itemsSize; i++) {
103796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            MenuItemImpl item = visibleItems.get(i);
103896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            if (item.requestsActionButton()) {
103996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell                item.setIsActionButton(maxActions > 0);
104096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell                maxActions--;
104196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            }
104296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
10438028dd32a4a04154050220dd0693583d5b750330Adam Powell
104496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mActionItems.clear();
104596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mNonActionItems.clear();
104696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        for (int i = 0; i < itemsSize; i++) {
104796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            MenuItemImpl item = visibleItems.get(i);
104896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            if (item.isActionButton()) {
104996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell                mActionItems.add(item);
105096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            } else {
105196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell                mNonActionItems.add(item);
105296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            }
105396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
10548028dd32a4a04154050220dd0693583d5b750330Adam Powell
105596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = false;
105696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
105796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
10588028dd32a4a04154050220dd0693583d5b750330Adam Powell    ArrayList<MenuItemImpl> getActionItems(boolean reserveActionOverflow) {
10598028dd32a4a04154050220dd0693583d5b750330Adam Powell        flagActionItems(reserveActionOverflow);
106096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mActionItems;
106196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
106296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
10638028dd32a4a04154050220dd0693583d5b750330Adam Powell    ArrayList<MenuItemImpl> getNonActionItems(boolean reserveActionOverflow) {
10648028dd32a4a04154050220dd0693583d5b750330Adam Powell        flagActionItems(reserveActionOverflow);
106596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mNonActionItems;
106696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
106796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
106896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    void setMaxActionItems(int maxActionItems) {
106996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mMaxActionItems = maxActionItems;
107096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = true;
107196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearHeader() {
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderIcon = null;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderTitle = null;
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderView = null;
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Drawable icon, final View view) {
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Resources r = getResources();
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (view != null) {
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderView = view;
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If using a custom view, then the title and icon aren't used
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderTitle = null;
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderIcon = null;
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (titleRes > 0) {
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderTitle = r.getText(titleRes);
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (title != null) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderTitle = title;
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (iconRes > 0) {
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderIcon = r.getDrawable(iconRes);
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (icon != null) {
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderIcon = icon;
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If using the title or icon, then a custom view isn't used
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderView = null;
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Notify of change
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's title. This replaces the header view. Called by the
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param title The new title.
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, title, 0, null, null);
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's title. This replaces the header view. Called by the
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param titleRes The new title (as a resource ID).
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderTitleInt(int titleRes) {
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(titleRes, null, 0, null, null);
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's icon. This replaces the header view. Called by the
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param icon The new icon.
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderIconInt(Drawable icon) {
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, 0, icon, null);
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's icon. This replaces the header view. Called by the
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param iconRes The new icon (as a resource ID).
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderIconInt(int iconRes) {
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, iconRes, null, null);
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's view. This replaces the title and icon. Called by the
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param view The new view.
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderViewInt(View view) {
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, 0, null, view);
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CharSequence getHeaderTitle() {
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderTitle;
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getHeaderIcon() {
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderIcon;
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getHeaderView() {
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderView;
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets the root menu (if this is a submenu, find its root menu).
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root menu.
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuBuilder getRootMenu() {
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the current menu info that is set on all items added to this menu
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (until this is called again with different menu info, in which case that
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one will be added to all subsequent item additions).
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuInfo The extra menu information to add.
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCurrentMenuInfo(ContextMenuInfo menuInfo) {
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurrentMenuInfo = menuInfo;
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets an adapter for providing items and their views.
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuType The type of menu to get an adapter for.
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A {@link MenuAdapter} for this menu with the given menu type.
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuAdapter getMenuAdapter(int menuType) {
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new MenuAdapter(menuType);
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12138028dd32a4a04154050220dd0693583d5b750330Adam Powell    /**
12148028dd32a4a04154050220dd0693583d5b750330Adam Powell     * Gets an adapter for providing overflow (non-action) items and their views.
12158028dd32a4a04154050220dd0693583d5b750330Adam Powell     *
12168028dd32a4a04154050220dd0693583d5b750330Adam Powell     * @param menuType The type of menu to get an adapter for.
12178028dd32a4a04154050220dd0693583d5b750330Adam Powell     * @return A {@link MenuAdapter} for this menu with the given menu type.
12188028dd32a4a04154050220dd0693583d5b750330Adam Powell     */
12198028dd32a4a04154050220dd0693583d5b750330Adam Powell    public MenuAdapter getOverflowMenuAdapter(int menuType) {
12208028dd32a4a04154050220dd0693583d5b750330Adam Powell        return new OverflowMenuAdapter(menuType);
12218028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
12228028dd32a4a04154050220dd0693583d5b750330Adam Powell
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setOptionalIconsVisible(boolean visible) {
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOptionalIconsVisible = visible;
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean getOptionalIconsVisible() {
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mOptionalIconsVisible;
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void saveHierarchyState(Bundle outState) {
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SparseArray<Parcelable> viewStates = new SparseArray<Parcelable>();
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType[] menuTypes = mMenuTypes;
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i] == null) {
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i].hasMenuView()) {
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((View) menuTypes[i].getMenuView(null)).saveHierarchyState(viewStates);
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        outState.putSparseParcelableArray(VIEWS_TAG, viewStates);
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void restoreHierarchyState(Bundle inState) {
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Save this for menu views opened later
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SparseArray<Parcelable> viewStates = mFrozenViewStates = inState
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getSparseParcelableArray(VIEWS_TAG);
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Thaw those menu views already open
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType[] menuTypes = mMenuTypes;
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i] == null) {
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i].hasMenuView()) {
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((View) menuTypes[i].getMenuView(null)).restoreHierarchyState(viewStates);
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * An adapter that allows an {@link AdapterView} to use this {@link MenuBuilder} as a data
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * source.  This adapter will use only the visible/shown items from the menu.
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class MenuAdapter extends BaseAdapter {
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mMenuType;
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public MenuAdapter(int menuType) {
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuType = menuType;
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getOffset() {
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuType == TYPE_EXPANDED) {
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getNumIconMenuItemsShown();
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getCount() {
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getVisibleItems().size() - getOffset();
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public MenuItemImpl getItem(int position) {
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getVisibleItems().get(position + getOffset());
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public long getItemId(int position) {
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Since a menu item's ID is optional, we'll use the position as an
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ID for the item in the AdapterView
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return position;
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View getView(int position, View convertView, ViewGroup parent) {
13004267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell            if (convertView != null) {
13014267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                MenuView.ItemView itemView = (MenuView.ItemView) convertView;
13024267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                itemView.getItemData().setItemView(mMenuType, null);
13034267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
13044267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                MenuItemImpl item = (MenuItemImpl) getItem(position);
13054267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                itemView.initialize(item, mMenuType);
13064267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                item.setItemView(mMenuType, itemView);
13074267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                return convertView;
13084267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell            } else {
13094267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                MenuItemImpl item = (MenuItemImpl) getItem(position);
13104267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                item.setItemView(mMenuType, null);
13114267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                return item.getItemView(mMenuType, parent);
13124267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell            }
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13148028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
13158028dd32a4a04154050220dd0693583d5b750330Adam Powell
13168028dd32a4a04154050220dd0693583d5b750330Adam Powell    /**
13178028dd32a4a04154050220dd0693583d5b750330Adam Powell     * An adapter that allows an {@link AdapterView} to use this {@link MenuBuilder} as a data
13188028dd32a4a04154050220dd0693583d5b750330Adam Powell     * source for overflow menu items that do not fit in the list of action items.
13198028dd32a4a04154050220dd0693583d5b750330Adam Powell     */
13208028dd32a4a04154050220dd0693583d5b750330Adam Powell    private class OverflowMenuAdapter extends MenuAdapter {
13218028dd32a4a04154050220dd0693583d5b750330Adam Powell        private ArrayList<MenuItemImpl> mOverflowItems;
13228028dd32a4a04154050220dd0693583d5b750330Adam Powell
13238028dd32a4a04154050220dd0693583d5b750330Adam Powell        public OverflowMenuAdapter(int menuType) {
13248028dd32a4a04154050220dd0693583d5b750330Adam Powell            super(menuType);
13258028dd32a4a04154050220dd0693583d5b750330Adam Powell            mOverflowItems = getNonActionItems(true);
13268028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13288028dd32a4a04154050220dd0693583d5b750330Adam Powell        @Override
13298028dd32a4a04154050220dd0693583d5b750330Adam Powell        public MenuItemImpl getItem(int position) {
13308028dd32a4a04154050220dd0693583d5b750330Adam Powell            return mOverflowItems.get(position);
13318028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
13328028dd32a4a04154050220dd0693583d5b750330Adam Powell
13338028dd32a4a04154050220dd0693583d5b750330Adam Powell        @Override
13348028dd32a4a04154050220dd0693583d5b750330Adam Powell        public int getCount() {
13358028dd32a4a04154050220dd0693583d5b750330Adam Powell            return mOverflowItems.size();
13368028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1339