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 Projectimport com.android.internal.view.menu.MenuBuilder.ItemInvoker; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewConfiguration; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The icon menu view is an icon-based menu usually with a subset of all the menu items. 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It is opened as the default menu, and shows either the first five or all six of the menu items 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with text and icon. In the situation of there being more than six items, the first five items 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be accompanied with a 'More' button that opens an {@link ExpandedMenuView} which lists 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all the menu items. 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#IconMenuView_rowHeight 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#IconMenuView_maxRows 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#IconMenuView_maxItemsPerRow 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class IconMenuView extends ViewGroup implements ItemInvoker, MenuView, Runnable { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ITEM_CAPTION_CYCLE_DELAY = 1000; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MenuBuilder mMenu; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Height of each row */ 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRowHeight; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Maximum number of rows to be shown */ 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMaxRows; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Maximum number of items to show in the icon menu. */ 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMaxItems; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Maximum number of items per row */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMaxItemsPerRow; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Actual number of items (the 'More' view does not count as an item) shown */ 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNumActualItemsShown; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Divider that is drawn between all rows */ 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mHorizontalDivider; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Height of the horizontal divider */ 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mHorizontalDividerHeight; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Set of horizontal divider positions where the horizontal divider will be drawn */ 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<Rect> mHorizontalDividerRects; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Divider that is drawn between all columns */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mVerticalDivider; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Width of the vertical divider */ 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVerticalDividerWidth; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Set of vertical divider positions where the vertical divider will be drawn */ 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<Rect> mVerticalDividerRects; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Icon for the 'More' button */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mMoreIcon; 83696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Background of each item (should contain the selected and focused states) */ 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mItemBackground; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default animations for this menu */ 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mAnimations; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Whether this IconMenuView has stale children and needs to update them. 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set true by {@link #markStaleChildren()} and reset to false by 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onMeasure(int, int)} 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mHasStaleChildren; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Longpress on MENU (while this is shown) switches to shortcut caption 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * mode. When the user releases the longpress, we do not want to pass the 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * key-up event up since that will dismiss the menu. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mMenuBeingLongpressed = false; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * While {@link #mMenuBeingLongpressed}, we toggle the children's caption 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * mode between each's title and its shortcut. This is the last caption mode 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we broadcasted to children. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mLastChildrenCaptionMode; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The layout to use for menu items. Each index is the row number (0 is the 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * top-most). Each value contains the number of items in that row. 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The length of this array should not be used to get the number of rows in 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the current layout, instead use {@link #mLayoutNumRows}. 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mLayout; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The number of rows in the current layout. 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mLayoutNumRows; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Instantiates the IconMenuView that is linked with the provided MenuBuilder. 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IconMenuView(Context context, AttributeSet attrs) { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.IconMenuView, 0, 0); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRowHeight = a.getDimensionPixelSize(com.android.internal.R.styleable.IconMenuView_rowHeight, 64); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMaxRows = a.getInt(com.android.internal.R.styleable.IconMenuView_maxRows, 2); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMaxItems = a.getInt(com.android.internal.R.styleable.IconMenuView_maxItems, 6); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMaxItemsPerRow = a.getInt(com.android.internal.R.styleable.IconMenuView_maxItemsPerRow, 3); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMoreIcon = a.getDrawable(com.android.internal.R.styleable.IconMenuView_moreIcon); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.MenuView, 0, 0); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItemBackground = a.getDrawable(com.android.internal.R.styleable.MenuView_itemBackground); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHorizontalDivider = a.getDrawable(com.android.internal.R.styleable.MenuView_horizontalDivider); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHorizontalDividerRects = new ArrayList<Rect>(); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVerticalDivider = a.getDrawable(com.android.internal.R.styleable.MenuView_verticalDivider); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVerticalDividerRects = new ArrayList<Rect>(); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAnimations = a.getResourceId(com.android.internal.R.styleable.MenuView_windowAnimationStyle, 0); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHorizontalDivider != null) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHorizontalDividerHeight = mHorizontalDivider.getIntrinsicHeight(); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure to have some height for the divider 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHorizontalDividerHeight == -1) mHorizontalDividerHeight = 1; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mVerticalDivider != null) { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVerticalDividerWidth = mVerticalDivider.getIntrinsicWidth(); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure to have some width for the divider 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mVerticalDividerWidth == -1) mVerticalDividerWidth = 1; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayout = new int[mMaxRows]; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This view will be drawing the dividers 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setWillNotDraw(false); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is so we'll receive the MENU key in touch mode 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setFocusableInTouchMode(true); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is so our children can still be arrow-key focused 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 172696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell int getMaxItems() { 173696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell return mMaxItems; 174696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 175696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Figures out the layout for the menu items. 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param width The available width for the icon menu. 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void layoutItems(int width) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numItems = getChildCount(); 18322cb2f46fdbb9a904ac394f488278fb47e2d4734Adam Powell if (numItems == 0) { 18422cb2f46fdbb9a904ac394f488278fb47e2d4734Adam Powell mLayoutNumRows = 0; 18522cb2f46fdbb9a904ac394f488278fb47e2d4734Adam Powell return; 18622cb2f46fdbb9a904ac394f488278fb47e2d4734Adam Powell } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Start with the least possible number of rows 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int curNumRows = 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Math.min((int) Math.ceil(numItems / (float) mMaxItemsPerRow), mMaxRows); 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Increase the number of rows until we find a configuration that fits 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all of the items' titles. Worst case, we use mMaxRows. 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (; curNumRows <= mMaxRows; curNumRows++) { 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layoutItemsUsingGravity(curNumRows, numItems); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (curNumRows >= numItems) { 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Can't have more rows than items 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (doItemsFit()) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // All the items fit, so this is a good configuration 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Figures out the layout for the menu items by equally distributing, and 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adding any excess items equally to lower rows. 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param numRows The total number of rows for the menu view 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param numItems The total number of items (across all rows) contained in 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the menu view 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return int[] Where the value of index i contains the number of items for row i 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void layoutItemsUsingGravity(int numRows, int numItems) { 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numBaseItemsPerRow = numItems / numRows; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numLeftoverItems = numItems % numRows; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The bottom rows will each get a leftover item. Rows (indexed at 0) 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that are >= this get a leftover item. Note: if there are 0 leftover 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * items, no rows will get them since this value will be greater than 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the last row. 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowsThatGetALeftoverItem = numRows - numLeftoverItems; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] layout = mLayout; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numRows; i++) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout[i] = numBaseItemsPerRow; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill the bottom rows with a leftover item each 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i >= rowsThatGetALeftoverItem) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout[i]++; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutNumRows = numRows; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Checks whether each item's title is fully visible using the current 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * layout. 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the items fit (each item's text is fully visible), false 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * otherwise. 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean doItemsFit() { 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int itemPos = 0; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] layout = mLayout; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numRows = mLayoutNumRows; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int row = 0; row < numRows; row++) { 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numItemsOnRow = layout[row]; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If there is only one item on this row, increasing the 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * number of rows won't help. 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (numItemsOnRow == 1) { 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemPos++; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int itemsOnRowCounter = numItemsOnRow; itemsOnRowCounter > 0; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemsOnRowCounter--) { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child = getChildAt(itemPos++); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutParams lp = (LayoutParams) child.getLayoutParams(); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lp.maxNumItemsOnRow < numItemsOnRow) { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 281696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell Drawable getItemBackgroundDrawable() { 282696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell return mItemBackground.getConstantState().newDrawable(getContext().getResources()); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates the item view for the 'More' button which is used to switch to 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the expanded menu view. This button is a special case since it does not 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * have a MenuItemData backing it. 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The IconMenuItemView for the 'More' button 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 291696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell IconMenuItemView createMoreItemView() { 292696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell Context context = getContext(); 293696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell LayoutInflater inflater = LayoutInflater.from(context); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IconMenuItemView itemView = (IconMenuItemView) inflater.inflate( 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.layout.icon_menu_item_layout, null); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 298696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell Resources r = context.getResources(); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemView.initialize(r.getText(com.android.internal.R.string.more_item_label), mMoreIcon); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set up a click listener on the view since there will be no invocation sequence 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // due to the lack of a MenuItemData this view 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemView.setOnClickListener(new OnClickListener() { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(View v) { 305696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell // Switches the menu to expanded mode. Requires support from 306696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell // the menu's active callback. 307696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mMenu.changeMenuMode(); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return itemView; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 315696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void initialize(MenuBuilder menu) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMenu = menu; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The positioning algorithm that gets called from onMeasure. It 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * just computes positions for each child, and then stores them in the child's layout params. 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param menuWidth The width of this menu to assume for positioning 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param menuHeight The height of this menu to assume for positioning 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void positionChildren(int menuWidth, int menuHeight) { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Clear the containers for the positions where the dividers should be drawn 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHorizontalDivider != null) mHorizontalDividerRects.clear(); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mVerticalDivider != null) mVerticalDividerRects.clear(); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the minimum number of rows needed 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numRows = mLayoutNumRows; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numRowsMinus1 = numRows - 1; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numItemsForRow[] = mLayout; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The item position across all rows 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int itemPos = 0; 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IconMenuView.LayoutParams childLayoutParams = null; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use float for this to get precise positions (uniform item widths 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // instead of last one taking any slack), and then convert to ints at last opportunity 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float itemLeft; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float itemTop = 0; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Since each row can have a different number of items, this will be computed per row 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float itemWidth; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Subtract the space needed for the horizontal dividers 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final float itemHeight = (menuHeight - mHorizontalDividerHeight * (numRows - 1)) 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project / (float)numRows; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int row = 0; row < numRows; row++) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Start at the left 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemLeft = 0; 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Subtract the space needed for the vertical dividers, and divide by the number of items 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemWidth = (menuWidth - mVerticalDividerWidth * (numItemsForRow[row] - 1)) 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project / (float)numItemsForRow[row]; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int itemPosOnRow = 0; itemPosOnRow < numItemsForRow[row]; itemPosOnRow++) { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Tell the child to be exactly this size 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = getChildAt(itemPos); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.measure(MeasureSpec.makeMeasureSpec((int) itemWidth, MeasureSpec.EXACTLY), 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MeasureSpec.makeMeasureSpec((int) itemHeight, MeasureSpec.EXACTLY)); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remember the child's position for layout 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLayoutParams = (IconMenuView.LayoutParams) child.getLayoutParams(); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLayoutParams.left = (int) itemLeft; 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLayoutParams.right = (int) (itemLeft + itemWidth); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLayoutParams.top = (int) itemTop; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLayoutParams.bottom = (int) (itemTop + itemHeight); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Increment by item width 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemLeft += itemWidth; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemPos++; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Add a vertical divider to draw 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mVerticalDivider != null) { 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVerticalDividerRects.add(new Rect((int) itemLeft, 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int) itemTop, (int) (itemLeft + mVerticalDividerWidth), 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int) (itemTop + itemHeight))); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Increment by divider width (even if we're not computing 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // dividers, since we need to leave room for them when 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // calculating item positions) 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemLeft += mVerticalDividerWidth; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Last child on each row should extend to very right edge 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childLayoutParams != null) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLayoutParams.right = menuWidth; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemTop += itemHeight; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Add a horizontal divider to draw 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mHorizontalDivider != null) && (row < numRowsMinus1)) { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHorizontalDividerRects.add(new Rect(0, (int) itemTop, menuWidth, 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int) (itemTop + mHorizontalDividerHeight))); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project itemTop += mHorizontalDividerHeight; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int measuredWidth = resolveSize(Integer.MAX_VALUE, widthMeasureSpec); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project calculateItemFittingMetadata(measuredWidth); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layoutItems(measuredWidth); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the desired height of the icon menu view (last row of items does 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // not have a divider below) 41322cb2f46fdbb9a904ac394f488278fb47e2d4734Adam Powell final int layoutNumRows = mLayoutNumRows; 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int desiredHeight = (mRowHeight + mHorizontalDividerHeight) * 41522cb2f46fdbb9a904ac394f488278fb47e2d4734Adam Powell layoutNumRows - mHorizontalDividerHeight; 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Maximum possible width and desired height 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMeasuredDimension(measuredWidth, 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resolveSize(desiredHeight, heightMeasureSpec)); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Position the children 42222cb2f46fdbb9a904ac394f488278fb47e2d4734Adam Powell if (layoutNumRows > 0) { 423189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn positionChildren(getMeasuredWidth(), getMeasuredHeight()); 42422cb2f46fdbb9a904ac394f488278fb47e2d4734Adam Powell } 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onLayout(boolean changed, int l, int t, int r, int b) { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IconMenuView.LayoutParams childLayoutParams; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = getChildCount() - 1; i >= 0; i--) { 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = getChildAt(i); 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLayoutParams = (IconMenuView.LayoutParams)child 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getLayoutParams(); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Layout children according to positions set during the measure 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.layout(childLayoutParams.left, childLayoutParams.top, childLayoutParams.right, 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLayoutParams.bottom); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onDraw(Canvas canvas) { 446809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy Drawable drawable = mHorizontalDivider; 447809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if (drawable != null) { 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If we have a horizontal divider to draw, draw it at the remembered positions 449809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final ArrayList<Rect> rects = mHorizontalDividerRects; 450809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy for (int i = rects.size() - 1; i >= 0; i--) { 451809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy drawable.setBounds(rects.get(i)); 452809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy drawable.draw(canvas); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 455809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 456809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy drawable = mVerticalDivider; 457809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if (drawable != null) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If we have a vertical divider to draw, draw it at the remembered positions 459809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final ArrayList<Rect> rects = mVerticalDividerRects; 460809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy for (int i = rects.size() - 1; i >= 0; i--) { 461809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy drawable.setBounds(rects.get(i)); 462809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy drawable.draw(canvas); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean invokeItem(MenuItemImpl item) { 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mMenu.performItemAction(item, 0); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 472809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy public LayoutParams generateLayoutParams(AttributeSet attrs) { 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new IconMenuView.LayoutParams(getContext(), attrs); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 477809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Override to allow type-checking of LayoutParams. 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return p instanceof IconMenuView.LayoutParams; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Marks as having stale children. 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void markStaleChildren() { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mHasStaleChildren) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHasStaleChildren = true; 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The number of actual items shown (those that are backed by an 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link MenuView.ItemView} implementation--eg: excludes More 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * item). 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int getNumActualItemsShown() { 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mNumActualItemsShown; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 501696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell void setNumActualItemsShown(int count) { 502696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mNumActualItemsShown = count; 503696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getWindowAnimations() { 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAnimations; 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of items per row. 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This should only be used for testing. 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The length of the array is the number of rows. A value at a 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * position is the number of items in that row. 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int[] getLayout() { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLayout; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of rows in the layout. 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This should only be used for testing. 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The length of the array is the number of rows. A value at a 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * position is the number of items in that row. 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLayoutNumRows() { 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mLayoutNumRows; 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean dispatchKeyEvent(KeyEvent event) { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeCallbacks(this); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project postDelayed(this, ViewConfiguration.getLongPressTimeout()); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (event.getAction() == KeyEvent.ACTION_UP) { 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMenuBeingLongpressed) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It was in cycle mode, so reset it (will also remove us 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // from being called back) 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCycleShortcutCaptionMode(false); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Just remove us from being called back 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeCallbacks(this); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fall through to normal processing too 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.dispatchKeyEvent(event); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onAttachedToWindow() { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onAttachedToWindow(); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestFocus(); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onDetachedFromWindow() { 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCycleShortcutCaptionMode(false); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onDetachedFromWindow(); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onWindowFocusChanged(boolean hasWindowFocus) { 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!hasWindowFocus) { 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCycleShortcutCaptionMode(false); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onWindowFocusChanged(hasWindowFocus); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the shortcut caption mode for IconMenuView. This mode will 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * continuously cycle between a child's shortcut and its title. 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cycleShortcutAndNormal Whether to go into cycling shortcut mode, 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or to go back to normal. 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setCycleShortcutCaptionMode(boolean cycleShortcutAndNormal) { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!cycleShortcutAndNormal) { 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We're setting back to title, so remove any callbacks for setting 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to shortcut 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeCallbacks(this); 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChildrenCaptionMode(false); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMenuBeingLongpressed = false; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set it the first time (the cycle will be started in run()). 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChildrenCaptionMode(true); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 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 * When this method is invoked if the menu is currently not being 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * longpressed, it means that the longpress has just been reached (so we set 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * longpress flag, and start cycling). If it is being longpressed, we cycle 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to the next mode. 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMenuBeingLongpressed) { 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Cycle to other caption mode on the children 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChildrenCaptionMode(!mLastChildrenCaptionMode); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Switch ourselves to continuously cycle the items captions 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMenuBeingLongpressed = true; 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setCycleShortcutCaptionMode(true); 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We should run again soon to cycle to the other caption mode 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project postDelayed(this, ITEM_CAPTION_CYCLE_DELAY); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Iterates children and sets the desired shortcut mode. Only 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setCycleShortcutCaptionMode(boolean)} and {@link #run()} should call 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this. 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param shortcut Whether to show shortcut or the title. 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setChildrenCaptionMode(boolean shortcut) { 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set the last caption mode pushed to children 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLastChildrenCaptionMode = shortcut; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = getChildCount() - 1; i >= 0; i--) { 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((IconMenuItemView) getChildAt(i)).setCaptionMode(shortcut); 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For each item, calculates the most dense row that fully shows the item's 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * title. 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param width The available width of the icon menu. 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void calculateItemFittingMetadata(int width) { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int maxNumItemsPerRow = mMaxItemsPerRow; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numItems = getChildCount(); 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numItems; i++) { 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams(); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Start with 1, since that case does not get covered in the loop below 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.maxNumItemsOnRow = 1; 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int curNumItemsPerRow = maxNumItemsPerRow; curNumItemsPerRow > 0; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project curNumItemsPerRow--) { 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check whether this item can fit into a row containing curNumItemsPerRow 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lp.desiredWidth < width / curNumItemsPerRow) { 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It can, mark this value as the most dense row it can fit into 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.maxNumItemsOnRow = curNumItemsPerRow; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Parcelable onSaveInstanceState() { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcelable superState = super.onSaveInstanceState(); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View focusedView = getFocusedChild(); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = getChildCount() - 1; i >= 0; i--) { 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getChildAt(i) == focusedView) { 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(superState, i); 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(superState, -1); 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onRestoreInstanceState(Parcelable state) { 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState ss = (SavedState) state; 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onRestoreInstanceState(ss.getSuperState()); 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ss.focusedPosition >= getChildCount()) { 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View v = getChildAt(ss.focusedPosition); 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v.requestFocus(); 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class SavedState extends BaseSavedState { 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int focusedPosition; 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link IconMenuView#onSaveInstanceState()} 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState(Parcelable superState, int focusedPosition) { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(superState); 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.focusedPosition = focusedPosition; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link #CREATOR} 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SavedState(Parcel in) { 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(in); 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project focusedPosition = in.readInt(); 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void writeToParcel(Parcel dest, int flags) { 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.writeToParcel(dest, flags); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest.writeInt(focusedPosition); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState createFromParcel(Parcel in) { 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(in); 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState[] newArray(int size) { 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState[size]; 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Layout parameters specific to IconMenuView (stores the left, top, right, bottom from the 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * measure pass). 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class LayoutParams extends ViewGroup.MarginLayoutParams 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int left, top, right, bottom; 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int desiredWidth; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int maxNumItemsOnRow; 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public LayoutParams(Context c, AttributeSet attrs) { 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(c, attrs); 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public LayoutParams(int width, int height) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(width, height); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 762