MenuBuilder.java revision 2fbf4de64f0ec5052201cea9519c44d5b1789a40
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;
322fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powellimport android.util.TypedValue;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextThemeWrapper;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyCharacterMap;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
3696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport android.view.LayoutInflater;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Menu;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MenuItem;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SubMenu;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextMenu.ContextMenuInfo;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.AdapterView;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.BaseAdapter;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
49e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roardimport java.util.Vector;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Implementation of the {@link android.view.Menu} interface for creating a
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * standard menu UI.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class MenuBuilder implements Menu {
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String LOGTAG = "MenuBuilder";
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The number of different menu types */
594267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public static final int NUM_TYPES = 5;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The menu type that represents the icon menu view */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_ICON = 0;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The menu type that represents the expanded menu view */
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_EXPANDED = 1;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The menu type that represents a menu dialog. Examples are context and sub
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * menus. This menu type will not have a corresponding MenuView, but it will
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * have an ItemView.
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int TYPE_DIALOG = 2;
7096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
7196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * The menu type that represents a button in the application's action bar.
7296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
7396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public static final int TYPE_ACTION_BUTTON = 3;
744267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    /**
754267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     * The menu type that represents a menu popup.
764267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     */
774267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public static final int TYPE_POPUP = 4;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String VIEWS_TAG = "android:views";
804267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
812fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell    private static final int THEME_SYSTEM_DEFAULT = 0;
822fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell    private static final int THEME_APPLICATION = -1;
832fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell    private static final int THEME_ALERT_DIALOG = -2;
842fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int THEME_RES_FOR_TYPE[] = new int[] {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.style.Theme_IconMenu,
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.style.Theme_ExpandedMenu,
892fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell        THEME_ALERT_DIALOG,
902fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell        THEME_APPLICATION,
912fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell        THEME_APPLICATION,
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int LAYOUT_RES_FOR_TYPE[] = new int[] {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.icon_menu_layout,
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.expanded_menu_layout,
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0,
9996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        com.android.internal.R.layout.action_menu_layout,
1004267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        0,
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Order must be the same order as the TYPE_*
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int ITEM_LAYOUT_RES_FOR_TYPE[] = new int[] {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.icon_menu_item_layout,
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.list_menu_item_layout,
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.layout.list_menu_item_layout,
10896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        com.android.internal.R.layout.action_menu_item_layout,
1090b2d306e7000f4c0c6ad4e00d494bb401d8a9fc2Adam Powell        com.android.internal.R.layout.popup_menu_item_layout,
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[]  sCategoryToOrder = new int[] {
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        1, /* No category */
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        4, /* CONTAINER */
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        5, /* SYSTEM */
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        3, /* SECONDARY */
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        2, /* ALTERNATIVE */
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        0, /* SELECTED_ALTERNATIVE */
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Resources mResources;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode()
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of accessing this directly.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mQwertyMode;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the shortcuts should be visible on menus. Use isShortcutsVisible()
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of accessing this directly.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mShortcutsVisible;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Callback that will receive the various menu-related events generated by
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this class. Use getCallback to get a reference to the callback.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Callback mCallback;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Contains all of the items for this menu */
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<MenuItemImpl> mItems;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Contains only the items that are currently visible.  This will be created/refreshed from
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getVisibleItems()} */
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<MenuItemImpl> mVisibleItems;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether or not the items (or any one item's shown state) has changed since it was last
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fetched from {@link #getVisibleItems()}
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsVisibleItemsStale;
15396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
15496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
15596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Contains only the items that should appear in the Action Bar, if present.
15696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
15796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private ArrayList<MenuItemImpl> mActionItems;
15896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
15996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Contains items that should NOT appear in the Action Bar, if present.
16096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
16196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private ArrayList<MenuItemImpl> mNonActionItems;
16296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
16396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * The number of visible action buttons permitted in this menu
16496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
16596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private int mMaxActionItems;
16696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
16796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Whether or not the items (or any one item's action state) has changed since it was
16896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * last fetched.
16996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
17096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private boolean mIsActionItemsStale;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1738028dd32a4a04154050220dd0693583d5b750330Adam Powell     * Whether the process of granting space as action items should reserve a space for
1748028dd32a4a04154050220dd0693583d5b750330Adam Powell     * an overflow option in the action list.
1758028dd32a4a04154050220dd0693583d5b750330Adam Powell     */
1768028dd32a4a04154050220dd0693583d5b750330Adam Powell    private boolean mReserveActionOverflow;
1778028dd32a4a04154050220dd0693583d5b750330Adam Powell
1788028dd32a4a04154050220dd0693583d5b750330Adam Powell    /**
1794d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell     * Default value for how added items should show in the action list.
1804d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell     */
1814d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell    private int mDefaultShowAsAction = MenuItem.SHOW_AS_ACTION_NEVER;
1824d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell
1834d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell    /**
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Current use case is Context Menus: As Views populate the context menu, each one has
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * extra information that should be passed along.  This is the current menu info that
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should be set on all items added to this menu.
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ContextMenuInfo mCurrentMenuInfo;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header title for menu types that have a header (context and submenus) */
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CharSequence mHeaderTitle;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header icon for menu types that have a header and support icons (context) */
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Drawable mHeaderIcon;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Header custom view for menu types that have a header and support custom views (context) */
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    View mHeaderView;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Contains the state of the View hierarchy for all menu views when the menu
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was frozen.
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SparseArray<Parcelable> mFrozenViewStates;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Prevents onItemsChanged from doing its junk, useful for batching commands
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that may individually call onItemsChanged.
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mPreventDispatchingItemsChanged = false;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mOptionalIconsVisible = false;
2102fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell
2112fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell    private static int getAlertDialogTheme(Context context) {
2122fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell        TypedValue outValue = new TypedValue();
2132fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell        context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
2142fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                outValue, true);
2152fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell        return outValue.resourceId;
2162fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell    }
2172fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MenuType[] mMenuTypes;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class MenuType {
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mMenuType;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The layout inflater that uses the menu type's theme */
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private LayoutInflater mInflater;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** The lazily loaded {@link MenuView} */
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private WeakReference<MenuView> mMenuView;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType(int menuType) {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuType = menuType;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater getInflater() {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Create an inflater that uses the given theme for the Views it inflates
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInflater == null) {
2352fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                Context wrappedContext;
236b3f245c30c022de8a26e016b7c9d5f13747b2868Adam Powell                int themeResForType = THEME_RES_FOR_TYPE[mMenuType];
2372fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                switch (themeResForType) {
2382fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                    case THEME_APPLICATION:
2392fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                        wrappedContext = new ContextThemeWrapper(mContext, themeResForType);
2402fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                        break;
2412fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                    case THEME_ALERT_DIALOG:
2422fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                        wrappedContext = new ContextThemeWrapper(mContext,
2432fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                                getAlertDialogTheme(mContext));
2442fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                        break;
2452fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                    default:
2462fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                        wrappedContext = mContext;
2472fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                        break;
2482fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell                }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInflater = (LayoutInflater) wrappedContext
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mInflater;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuView getMenuView(ViewGroup parent) {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (LAYOUT_RES_FOR_TYPE[mMenuType] == 0) {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MenuView menuView = mMenuView != null ? mMenuView.get() : null;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (menuView == null) {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView = (MenuView) getInflater().inflate(
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            LAYOUT_RES_FOR_TYPE[mMenuType], parent, false);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView.initialize(MenuBuilder.this, mMenuType);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Cache the view
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mMenuView = new WeakReference<MenuView>(menuView);
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mFrozenViewStates != null) {
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        View view = (View) menuView;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        view.restoreHierarchyState(mFrozenViewStates);
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Clear this menu type's frozen state, since we just restored it
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mFrozenViewStates.remove(view.getId());
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return menuView;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasMenuView() {
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mMenuView != null && mMenuView.get() != null;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by menu to notify of close and selection changes
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface Callback {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a menu item is selected.
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu The menu that is the parent of the item
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param item The menu item that is selected
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return whether the menu item selection was handled
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a menu is closed.
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu The menu that was closed.
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param allMenusAreClosing Whether the menus are completely closing (true),
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            or whether there is another menu opening shortly
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            (false). For example, if the menu is closing because a
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            sub menu is about to be shown, <var>allMenusAreClosing</var>
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *            is false.
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a sub menu is selected.  This is a cue to open the given sub menu's decor.
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param subMenu the sub menu that is being opened
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return whether the sub menu selection was handled by the callback
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onSubMenuSelected(SubMenuBuilder subMenu);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when a sub menu is closed
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu the sub menu that was closed
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onCloseSubMenu(SubMenuBuilder menu);
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when the mode of the menu changes (for example, from icon to expanded).
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param menu the menu that has changed modes
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onMenuModeChange(MenuBuilder menu);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by menu items to execute their associated action
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface ItemInvoker {
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean invokeItem(MenuItemImpl item);
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuBuilder(Context context) {
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMenuTypes = new MenuType[NUM_TYPES];
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResources = context.getResources();
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems = new ArrayList<MenuItemImpl>();
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVisibleItems = new ArrayList<MenuItemImpl>();
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsVisibleItemsStale = true;
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
35296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mActionItems = new ArrayList<MenuItemImpl>();
35396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mNonActionItems = new ArrayList<MenuItemImpl>();
35496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = true;
35596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShortcutsVisible =
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS);
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3604d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell    public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
3614d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell        mDefaultShowAsAction = defaultShowAsAction;
3624d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell        return this;
3634d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell    }
3644d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCallback(Callback callback) {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCallback = callback;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MenuType getMenuType(int menuType) {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mMenuTypes[menuType] == null) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuTypes[menuType] = new MenuType(menuType);
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mMenuTypes[menuType];
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets a menu View that contains this menu's items.
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuType The type of menu to get a View for (must be one of
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #TYPE_ICON}, {@link #TYPE_EXPANDED},
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #TYPE_DIALOG}).
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parent The ViewGroup that provides a set of LayoutParams values
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            for this menu view
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A View for the menu of type <var>menuType</var>
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getMenuView(int menuType, ViewGroup parent) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The expanded menu depends on the number if items shown in the icon menu (which
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // is adjustable as setters/XML attributes on IconMenuView [imagine a larger LCD
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // wanting to show more icons]). If, for example, the activity goes through
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // an orientation change while the expanded menu is open, the icon menu's view
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // won't have an instance anymore; so here we make sure we have an icon menu view (matching
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the same parent so the layout parameters from the XML are used). This
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // will create the icon menu view and cache it (if it doesn't already exist).
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (menuType == TYPE_EXPANDED
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mMenuTypes[TYPE_ICON] == null || !mMenuTypes[TYPE_ICON].hasMenuView())) {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            getMenuType(TYPE_ICON).getMenuView(parent);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (View) getMenuType(menuType).getMenuView(parent);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getNumIconMenuItemsShown() {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ViewGroup parent = null;
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMenuTypes[TYPE_ICON].hasMenuView()) {
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * There isn't an icon menu view instantiated, so when we get it
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * below, it will lazily instantiate it. We should pass a proper
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * parent so it uses the layout_ attributes present in the XML
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * layout file.
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuTypes[TYPE_EXPANDED].hasMenuView()) {
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                View expandedMenuView = (View) mMenuTypes[TYPE_EXPANDED].getMenuView(null);
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                parent = (ViewGroup) expandedMenuView.getParent();
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ((IconMenuView) getMenuView(TYPE_ICON, parent)).getNumActualItemsShown();
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clears the cached menu views. Call this if the menu views need to another
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * layout (for example, if the screen size has changed).
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearMenuViews() {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuTypes[i] != null) {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMenuTypes[i].mMenuView = null;
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = mItems.size() - 1; i >= 0; i--) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((SubMenuBuilder) item.getSubMenu()).clearMenuViews();
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.clearItemViews();
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Adds an item to the menu.  The other add methods funnel to this.
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int ordering = getOrdering(categoryOrder);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4484d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell        final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder,
4494d9861e7ec8488634d316b20981464de2ab7b6feAdam Powell                ordering, title, mDefaultShowAsAction);
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrentMenuInfo != null) {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Pass along the current menu info
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.setMenuInfo(mCurrentMenuInfo);
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.add(findInsertIndex(mItems, ordering), item);
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return item;
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(CharSequence title) {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(0, 0, 0, title);
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int titleRes) {
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(0, 0, 0, mResources.getString(titleRes));
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int group, int id, int categoryOrder, CharSequence title) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(group, id, categoryOrder, title);
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem add(int group, int id, int categoryOrder, int title) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addInternal(group, id, categoryOrder, mResources.getString(title));
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(CharSequence title) {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(0, 0, 0, title);
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int titleRes) {
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(0, 0, 0, mResources.getString(titleRes));
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        item.setSubMenu(subMenu);
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return subMenu;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return addSubMenu(group, id, categoryOrder, mResources.getString(title));
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller,
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PackageManager pm = mContext.getPackageManager();
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final List<ResolveInfo> lri =
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pm.queryIntentActivityOptions(caller, specifics, intent, 0);
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = lri != null ? lri.size() : 0;
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            removeGroup(group);
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ResolveInfo ri = lri.get(i);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent rintent = new Intent(
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rintent.setComponent(new ComponentName(
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.applicationInfo.packageName,
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ri.activityInfo.name));
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm))
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .setIcon(ri.loadIcon(pm))
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    .setIntent(rintent);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (outSpecificItems != null && ri.specificIndex >= 0) {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                outSpecificItems[ri.specificIndex] = item;
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return N;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeItem(int id) {
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeItemAtInt(findItemIndex(id), true);
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGroup(int group) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int i = findGroupIndex(group);
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i >= 0) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int maxRemovable = mItems.size() - i;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int numRemoved = 0;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) {
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't force update for each one, this method will do it at the end
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeItemAtInt(i, false);
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Notify menu views
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onItemsChanged(false);
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove the item at the given index and optionally forces menu views to
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * update.
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param index The index of the item to be removed. If this index is
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            invalid an exception is thrown.
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param updateChildrenOnMenuViews Whether to force update on menu views.
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            Please make sure you eventually call this after your batch of
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            removals.
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((index < 0) || (index >= mItems.size())) return;
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.remove(index);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (updateChildrenOnMenuViews) onItemsChanged(false);
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeItemAt(int index) {
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeItemAtInt(index, true);
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearAll() {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreventDispatchingItemsChanged = true;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clear();
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clearHeader();
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPreventDispatchingItemsChanged = false;
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(true);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clear() {
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItems.clear();
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(true);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setExclusiveItemChecked(MenuItem item) {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int group = item.getGroupId();
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl curItem = mItems.get(i);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (curItem.getGroupId() == group) {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!curItem.isExclusiveCheckable()) continue;
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!curItem.isCheckable()) continue;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check the item meant to be checked, uncheck the others (that are in the group)
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curItem.setCheckedInt(curItem == item);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setExclusiveCheckable(exclusive);
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setCheckable(checkable);
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupVisible(int group, boolean visible) {
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // than setVisible and at the end notify of items being changed
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean changedAtLeastOneItem = false;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (changedAtLeastOneItem) onItemsChanged(false);
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGroupEnabled(int group, boolean enabled) {
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                item.setEnabled(enabled);
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasVisibleItems() {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.isVisible()) {
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem findItem(int id) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getItemId() == id) {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return item;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (item.hasSubMenu()) {
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                MenuItem possibleItem = item.getSubMenu().findItem(id);
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (possibleItem != null) {
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return possibleItem;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findItemIndex(int id) {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < size; i++) {
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getItemId() == id) {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findGroupIndex(int group) {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return findGroupIndex(group, 0);
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int findGroupIndex(int group, int start) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = size();
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (start < 0) {
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            start = 0;
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = start; i < size; i++) {
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final MenuItemImpl item = mItems.get(i);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getGroupId() == group) {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i;
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int size() {
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mItems.size();
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** {@inheritDoc} */
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuItem getItem(int index) {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mItems.get(index);
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7148028dd32a4a04154050220dd0693583d5b750330Adam Powell    public MenuItem getOverflowItem(int index) {
7158028dd32a4a04154050220dd0693583d5b750330Adam Powell        flagActionItems(true);
7168028dd32a4a04154050220dd0693583d5b750330Adam Powell        return mNonActionItems.get(index);
7178028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
7188028dd32a4a04154050220dd0693583d5b750330Adam Powell
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShortcutKey(int keyCode, KeyEvent event) {
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return findItemWithShortcutForKey(keyCode, event) != null;
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setQwertyMode(boolean isQwerty) {
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyMode = isQwerty;
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        refreshShortcuts(isShortcutsVisible(), isQwerty);
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the ordering across all items. This will grab the category from
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the upper bits, find out how to order the category with respect to other
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * categories, and combine it with the lower bits.
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param categoryOrder The category order for a particular item (if it has
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            not been or/add with a category, the default category is
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            assumed).
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return An ordering integer that can be used to order this item across
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         all the items (even from other categories).
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int getOrdering(int categoryOrder)
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index < 0 || index >= sCategoryToOrder.length) {
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("order does not contain a valid category.");
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return whether the menu shortcuts are in qwerty mode or not
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean isQwertyMode() {
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mQwertyMode;
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Refreshes the shortcut labels on each of the displayed items.  Passes the arguments
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * so submenus don't need to call their parent menu for the same values.
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void refreshShortcuts(boolean shortcutsVisible, boolean qwertyMode) {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl item;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = mItems.size() - 1; i >= 0; i--) {
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item = mItems.get(i);
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((MenuBuilder) item.getSubMenu()).refreshShortcuts(shortcutsVisible, qwertyMode);
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item.refreshShortcutOnItemViews(shortcutsVisible, qwertyMode);
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets whether the shortcuts should be visible on menus.  Devices without hardware
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * key input will never make shortcuts visible even if this method is passed 'true'.
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param shortcutsVisible Whether shortcuts should be visible (if true and a
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            menu item does not have a shortcut defined, that item will
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            still NOT show a shortcut)
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setShortcutsVisible(boolean shortcutsVisible) {
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShortcutsVisible == shortcutsVisible) return;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShortcutsVisible =
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS)
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && shortcutsVisible;
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        refreshShortcuts(mShortcutsVisible, isQwertyMode());
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Whether shortcuts should be visible on menus.
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShortcutsVisible() {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mShortcutsVisible;
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Resources getResources() {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mResources;
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Callback getCallback() {
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCallback;
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getContext() {
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContext;
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = items.size() - 1; i >= 0; i--) {
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = items.get(i);
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.getOrdering() <= ordering) {
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return i + 1;
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event);
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean handled = false;
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (item != null) {
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handled = performItemAction(item, flags);
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) {
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(true);
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return handled;
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    /*
840e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * This function will return all the menu and sub-menu items that can
841e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * be directly (the shortcut directly corresponds) and indirectly
842e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * (the ALT-enabled char corresponds to the shortcut) associated
843e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * with the keyCode.
844e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     */
845e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    List<MenuItemImpl> findItemsWithShortcutForKey(int keyCode, KeyEvent event) {
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean qwerty = isQwertyMode();
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int metaState = event.getMetaState();
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get the chars associated with the keyCode (i.e using any chording combo)
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The delete key is not mapped to '\b' so we treat it specially
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
856e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        Vector<MenuItemImpl> items = new Vector();
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Look for an item whose shortcut is this key.
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = mItems.size();
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuItemImpl item = mItems.get(i);
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.hasSubMenu()) {
862e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                List<MenuItemImpl> subMenuItems = ((MenuBuilder)item.getSubMenu())
863e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    .findItemsWithShortcutForKey(keyCode, event);
864e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                items.addAll(subMenuItems);
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
866e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
867e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) &&
868e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  (shortcutChar != 0) &&
869e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  (shortcutChar == possibleChars.meta[0]
870e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                      || shortcutChar == possibleChars.meta[2]
871e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                      || (qwerty && shortcutChar == '\b' &&
872e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                          keyCode == KeyEvent.KEYCODE_DEL)) &&
873e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                  item.isEnabled()) {
874e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                items.add(item);
875e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            }
876e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
877e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        return items;
878e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    }
879e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
880e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    /*
881e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * We want to return the menu item associated with the key, but if there is no
882e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * ambiguity (i.e. there is only one menu item corresponding to the key) we want
883e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * to return it even if it's not an exact match; this allow the user to
884e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * _not_ use the ALT key for example, making the use of shortcuts slightly more
885e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
886e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
887e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     *
888e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * On the other hand, if two (or more) shortcuts corresponds to the same key,
889e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     * we have to only return the exact match.
890e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard     */
891e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard    MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
892e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // Get all items that can be associated directly or indirectly with the keyCode
893e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        List<MenuItemImpl> items = findItemsWithShortcutForKey(keyCode, event);
894e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
895e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        if (items == null) {
896e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            return null;
897e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
898e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
899e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final int metaState = event.getMetaState();
900e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
901e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // Get the chars associated with the keyCode (i.e using any chording combo)
902e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        event.getKeyData(possibleChars);
903e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
904e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // If we have only one element, we can safely returns it
905e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        if (items.size() == 1) {
906e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            return items.get(0);
907e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        }
908e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
909e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        final boolean qwerty = isQwertyMode();
910e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // If we found more than one item associated with the key,
911e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        // we have to return the exact match
912e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard        for (MenuItemImpl item : items) {
913e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
914e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard            if ((shortcutChar == possibleChars.meta[0] &&
915e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    (metaState & KeyEvent.META_ALT_ON) == 0)
916e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                || (shortcutChar == possibleChars.meta[2] &&
917e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    (metaState & KeyEvent.META_ALT_ON) != 0)
918e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                || (qwerty && shortcutChar == '\b' &&
919e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                    keyCode == KeyEvent.KEYCODE_DEL)) {
920e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard                return item;
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
925e0fc838ebc18e327a399902cacae16bdbbc09627Nicolas Roard
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performIdentifierAction(int id, int flags) {
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Look for an item whose identifier is the id.
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return performItemAction(findItem(id), flags);
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performItemAction(MenuItem item, int flags) {
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl itemImpl = (MenuItemImpl) item;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (itemImpl == null || !itemImpl.isEnabled()) {
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean invoked = itemImpl.invoke();
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (item.hasSubMenu()) {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            close(false);
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCallback != null) {
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Return true if the sub menu was invoked or the item was invoked previously
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                invoked = mCallback.onSubMenuSelected((SubMenuBuilder) item.getSubMenu())
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || invoked;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                close(true);
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return invoked;
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Closes the visible menu.
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param allMenusAreClosing Whether the menus are completely closing (true),
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            or whether there is another menu coming in this menu's place
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            (false). For example, if the menu is closing because a
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            sub menu is about to be shown, <var>allMenusAreClosing</var>
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            is false.
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void close(boolean allMenusAreClosing) {
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Callback callback = getCallback();
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (callback != null) {
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            callback.onCloseMenu(this, allMenusAreClosing);
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** {@inheritDoc} */
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void close() {
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close(true);
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when an item is added or removed.
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cleared Whether the items were cleared or just changed.
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void onItemsChanged(boolean cleared) {
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mPreventDispatchingItemsChanged) {
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsVisibleItemsStale == false) mIsVisibleItemsStale = true;
98696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            if (mIsActionItemsStale == false) mIsActionItemsStale = true;
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MenuType[] menuTypes = mMenuTypes;
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < NUM_TYPES; i++) {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((menuTypes[i] != null) && (menuTypes[i].hasMenuView())) {
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MenuView menuView = menuTypes[i].mMenuView.get();
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    menuView.updateChildren(cleared);
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called by {@link MenuItemImpl} when its visible flag is changed.
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param item The item that has gone through a visibility change.
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void onItemVisibleChanged(MenuItemImpl item) {
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Notify of items being changed
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
100796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    /**
100896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * Called by {@link MenuItemImpl} when its action request status is changed.
100996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     * @param item The item that has gone through a change in action request status.
101096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell     */
101196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    void onItemActionRequestChanged(MenuItemImpl item) {
101296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        // Notify of items being changed
101396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        onItemsChanged(false);
101496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
101596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<MenuItemImpl> getVisibleItems() {
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mIsVisibleItemsStale) return mVisibleItems;
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Refresh the visible items
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVisibleItems.clear();
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int itemsSize = mItems.size();
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuItemImpl item;
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < itemsSize; i++) {
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            item = mItems.get(i);
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (item.isVisible()) mVisibleItems.add(item);
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsVisibleItemsStale = false;
103096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = true;
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mVisibleItems;
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
103496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
10358028dd32a4a04154050220dd0693583d5b750330Adam Powell    private void flagActionItems(boolean reserveActionOverflow) {
10368028dd32a4a04154050220dd0693583d5b750330Adam Powell        if (reserveActionOverflow != mReserveActionOverflow) {
10378028dd32a4a04154050220dd0693583d5b750330Adam Powell            mReserveActionOverflow = reserveActionOverflow;
10388028dd32a4a04154050220dd0693583d5b750330Adam Powell            mIsActionItemsStale = true;
10398028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
10408028dd32a4a04154050220dd0693583d5b750330Adam Powell
104196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        if (!mIsActionItemsStale) {
104296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            return;
104396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
10448028dd32a4a04154050220dd0693583d5b750330Adam Powell
104596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        final ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
104696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        final int itemsSize = visibleItems.size();
104796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        int maxActions = mMaxActionItems;
10488028dd32a4a04154050220dd0693583d5b750330Adam Powell
10498028dd32a4a04154050220dd0693583d5b750330Adam Powell        int requiredItems = 0;
10508028dd32a4a04154050220dd0693583d5b750330Adam Powell        int requestedItems = 0;
10518028dd32a4a04154050220dd0693583d5b750330Adam Powell        boolean hasOverflow = false;
105296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        for (int i = 0; i < itemsSize; i++) {
105396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            MenuItemImpl item = visibleItems.get(i);
105496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            if (item.requiresActionButton()) {
10558028dd32a4a04154050220dd0693583d5b750330Adam Powell                requiredItems++;
10568028dd32a4a04154050220dd0693583d5b750330Adam Powell            } else if (item.requestsActionButton()) {
10578028dd32a4a04154050220dd0693583d5b750330Adam Powell                requestedItems++;
10588028dd32a4a04154050220dd0693583d5b750330Adam Powell            } else {
10598028dd32a4a04154050220dd0693583d5b750330Adam Powell                hasOverflow = true;
106096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            }
106196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
10628028dd32a4a04154050220dd0693583d5b750330Adam Powell
10638028dd32a4a04154050220dd0693583d5b750330Adam Powell        // Reserve a spot for the overflow item if needed.
10648028dd32a4a04154050220dd0693583d5b750330Adam Powell        if (reserveActionOverflow &&
10658028dd32a4a04154050220dd0693583d5b750330Adam Powell                (hasOverflow || requiredItems + requestedItems > maxActions)) {
10668028dd32a4a04154050220dd0693583d5b750330Adam Powell            maxActions--;
10678028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
10688028dd32a4a04154050220dd0693583d5b750330Adam Powell        maxActions -= requiredItems;
10698028dd32a4a04154050220dd0693583d5b750330Adam Powell
107096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        // Flag as many more requested items as will fit.
107196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        for (int i = 0; i < itemsSize; i++) {
107296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            MenuItemImpl item = visibleItems.get(i);
107396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            if (item.requestsActionButton()) {
107496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell                item.setIsActionButton(maxActions > 0);
107596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell                maxActions--;
107696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            }
107796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
10788028dd32a4a04154050220dd0693583d5b750330Adam Powell
107996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mActionItems.clear();
108096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mNonActionItems.clear();
108196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        for (int i = 0; i < itemsSize; i++) {
108296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            MenuItemImpl item = visibleItems.get(i);
108396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            if (item.isActionButton()) {
108496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell                mActionItems.add(item);
108596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            } else {
108696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell                mNonActionItems.add(item);
108796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            }
108896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
10898028dd32a4a04154050220dd0693583d5b750330Adam Powell
109096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = false;
109196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
109296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
10938028dd32a4a04154050220dd0693583d5b750330Adam Powell    ArrayList<MenuItemImpl> getActionItems(boolean reserveActionOverflow) {
10948028dd32a4a04154050220dd0693583d5b750330Adam Powell        flagActionItems(reserveActionOverflow);
109596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mActionItems;
109696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
109796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
10988028dd32a4a04154050220dd0693583d5b750330Adam Powell    ArrayList<MenuItemImpl> getNonActionItems(boolean reserveActionOverflow) {
10998028dd32a4a04154050220dd0693583d5b750330Adam Powell        flagActionItems(reserveActionOverflow);
110096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mNonActionItems;
110196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
110296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
110396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    void setMaxActionItems(int maxActionItems) {
110496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mMaxActionItems = maxActionItems;
110596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mIsActionItemsStale = true;
110696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearHeader() {
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderIcon = null;
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderTitle = null;
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeaderView = null;
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes,
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Drawable icon, final View view) {
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Resources r = getResources();
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (view != null) {
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderView = view;
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If using a custom view, then the title and icon aren't used
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderTitle = null;
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderIcon = null;
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (titleRes > 0) {
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderTitle = r.getText(titleRes);
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (title != null) {
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderTitle = title;
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (iconRes > 0) {
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderIcon = r.getDrawable(iconRes);
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (icon != null) {
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHeaderIcon = icon;
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If using the title or icon, then a custom view isn't used
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeaderView = null;
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Notify of change
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        onItemsChanged(false);
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's title. This replaces the header view. Called by the
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param title The new title.
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderTitleInt(CharSequence title) {
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, title, 0, null, null);
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's title. This replaces the header view. Called by the
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param titleRes The new title (as a resource ID).
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderTitleInt(int titleRes) {
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(titleRes, null, 0, null, null);
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's icon. This replaces the header view. Called by the
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param icon The new icon.
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderIconInt(Drawable icon) {
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, 0, icon, null);
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's icon. This replaces the header view. Called by the
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param iconRes The new icon (as a resource ID).
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderIconInt(int iconRes) {
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, iconRes, null, null);
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the header's view. This replaces the title and icon. Called by the
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * builder-style methods of subclasses.
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param view The new view.
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return This MenuBuilder so additional setters can be called.
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected MenuBuilder setHeaderViewInt(View view) {
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeaderInternal(0, null, 0, null, view);
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CharSequence getHeaderTitle() {
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderTitle;
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getHeaderIcon() {
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderIcon;
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getHeaderView() {
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeaderView;
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets the root menu (if this is a submenu, find its root menu).
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The root menu.
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuBuilder getRootMenu() {
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the current menu info that is set on all items added to this menu
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (until this is called again with different menu info, in which case that
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * one will be added to all subsequent item additions).
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuInfo The extra menu information to add.
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCurrentMenuInfo(ContextMenuInfo menuInfo) {
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurrentMenuInfo = menuInfo;
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets an adapter for providing items and their views.
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param menuType The type of menu to get an adapter for.
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A {@link MenuAdapter} for this menu with the given menu type.
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuAdapter getMenuAdapter(int menuType) {
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new MenuAdapter(menuType);
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12488028dd32a4a04154050220dd0693583d5b750330Adam Powell    /**
12498028dd32a4a04154050220dd0693583d5b750330Adam Powell     * Gets an adapter for providing overflow (non-action) items and their views.
12508028dd32a4a04154050220dd0693583d5b750330Adam Powell     *
12518028dd32a4a04154050220dd0693583d5b750330Adam Powell     * @param menuType The type of menu to get an adapter for.
12528028dd32a4a04154050220dd0693583d5b750330Adam Powell     * @return A {@link MenuAdapter} for this menu with the given menu type.
12538028dd32a4a04154050220dd0693583d5b750330Adam Powell     */
12548028dd32a4a04154050220dd0693583d5b750330Adam Powell    public MenuAdapter getOverflowMenuAdapter(int menuType) {
12558028dd32a4a04154050220dd0693583d5b750330Adam Powell        return new OverflowMenuAdapter(menuType);
12568028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
12578028dd32a4a04154050220dd0693583d5b750330Adam Powell
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setOptionalIconsVisible(boolean visible) {
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOptionalIconsVisible = visible;
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean getOptionalIconsVisible() {
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mOptionalIconsVisible;
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void saveHierarchyState(Bundle outState) {
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SparseArray<Parcelable> viewStates = new SparseArray<Parcelable>();
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType[] menuTypes = mMenuTypes;
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i] == null) {
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i].hasMenuView()) {
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((View) menuTypes[i].getMenuView(null)).saveHierarchyState(viewStates);
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        outState.putSparseParcelableArray(VIEWS_TAG, viewStates);
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void restoreHierarchyState(Bundle inState) {
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Save this for menu views opened later
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SparseArray<Parcelable> viewStates = mFrozenViewStates = inState
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getSparseParcelableArray(VIEWS_TAG);
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Thaw those menu views already open
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MenuType[] menuTypes = mMenuTypes;
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = NUM_TYPES - 1; i >= 0; i--) {
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i] == null) {
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (menuTypes[i].hasMenuView()) {
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ((View) menuTypes[i].getMenuView(null)).restoreHierarchyState(viewStates);
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * An adapter that allows an {@link AdapterView} to use this {@link MenuBuilder} as a data
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * source.  This adapter will use only the visible/shown items from the menu.
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class MenuAdapter extends BaseAdapter {
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private int mMenuType;
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public MenuAdapter(int menuType) {
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMenuType = menuType;
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getOffset() {
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMenuType == TYPE_EXPANDED) {
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return getNumIconMenuItemsShown();
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getCount() {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getVisibleItems().size() - getOffset();
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public MenuItemImpl getItem(int position) {
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getVisibleItems().get(position + getOffset());
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public long getItemId(int position) {
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Since a menu item's ID is optional, we'll use the position as an
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ID for the item in the AdapterView
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return position;
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View getView(int position, View convertView, ViewGroup parent) {
13354267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell            if (convertView != null) {
13364267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                MenuView.ItemView itemView = (MenuView.ItemView) convertView;
13374267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                itemView.getItemData().setItemView(mMenuType, null);
13384267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
13394267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                MenuItemImpl item = (MenuItemImpl) getItem(position);
13404267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                itemView.initialize(item, mMenuType);
13414267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                item.setItemView(mMenuType, itemView);
13424267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                return convertView;
13434267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell            } else {
13444267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                MenuItemImpl item = (MenuItemImpl) getItem(position);
13454267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                item.setItemView(mMenuType, null);
13464267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell                return item.getItemView(mMenuType, parent);
13474267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell            }
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13498028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
13508028dd32a4a04154050220dd0693583d5b750330Adam Powell
13518028dd32a4a04154050220dd0693583d5b750330Adam Powell    /**
13528028dd32a4a04154050220dd0693583d5b750330Adam Powell     * An adapter that allows an {@link AdapterView} to use this {@link MenuBuilder} as a data
13538028dd32a4a04154050220dd0693583d5b750330Adam Powell     * source for overflow menu items that do not fit in the list of action items.
13548028dd32a4a04154050220dd0693583d5b750330Adam Powell     */
13558028dd32a4a04154050220dd0693583d5b750330Adam Powell    private class OverflowMenuAdapter extends MenuAdapter {
13568028dd32a4a04154050220dd0693583d5b750330Adam Powell        private ArrayList<MenuItemImpl> mOverflowItems;
13578028dd32a4a04154050220dd0693583d5b750330Adam Powell
13588028dd32a4a04154050220dd0693583d5b750330Adam Powell        public OverflowMenuAdapter(int menuType) {
13598028dd32a4a04154050220dd0693583d5b750330Adam Powell            super(menuType);
13608028dd32a4a04154050220dd0693583d5b750330Adam Powell            mOverflowItems = getNonActionItems(true);
13618028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13638028dd32a4a04154050220dd0693583d5b750330Adam Powell        @Override
13648028dd32a4a04154050220dd0693583d5b750330Adam Powell        public MenuItemImpl getItem(int position) {
13658028dd32a4a04154050220dd0693583d5b750330Adam Powell            return mOverflowItems.get(position);
13668028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
13678028dd32a4a04154050220dd0693583d5b750330Adam Powell
13688028dd32a4a04154050220dd0693583d5b750330Adam Powell        @Override
13698028dd32a4a04154050220dd0693583d5b750330Adam Powell        public int getCount() {
13708028dd32a4a04154050220dd0693583d5b750330Adam Powell            return mOverflowItems.size();
13718028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1374