ActionMenuView.java revision 3f476b34049d062942eafcf48396f593e00bd324
196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell/*
296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Copyright (C) 2010 The Android Open Source Project
396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell *
496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Licensed under the Apache License, Version 2.0 (the "License");
596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * you may not use this file except in compliance with the License.
696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * You may obtain a copy of the License at
796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell *
896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell *      http://www.apache.org/licenses/LICENSE-2.0
996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell *
1096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Unless required by applicable law or agreed to in writing, software
1196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * distributed under the License is distributed on an "AS IS" BASIS,
1296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * See the License for the specific language governing permissions and
1496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * limitations under the License.
1596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */
1696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellpackage com.android.internal.view.menu;
1796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
1896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport android.content.Context;
198028dd32a4a04154050220dd0693583d5b750330Adam Powellimport android.content.res.Configuration;
207ade1be822ed05a143b059319dccd5e9f623b56dAdam Powellimport android.content.res.Resources;
217ade1be822ed05a143b059319dccd5e9f623b56dAdam Powellimport android.content.res.TypedArray;
22be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powellimport android.graphics.drawable.Drawable;
2396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport android.util.AttributeSet;
246b336f835d637853800b94689375a03f337139a4Adam Powellimport android.view.Gravity;
253f476b34049d062942eafcf48396f593e00bd324Adam Powellimport android.view.LayoutInflater;
26cf78b3e5101349fdddbde14b3a55140f9562ae66Adam Powellimport android.view.View;
277ade1be822ed05a143b059319dccd5e9f623b56dAdam Powellimport android.view.ViewGroup;
289ab978713ce86fdaefed2407f4f3c998ab0e3178Adam Powellimport android.view.ViewParent;
298028dd32a4a04154050220dd0693583d5b750330Adam Powellimport android.widget.ImageButton;
30be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powellimport android.widget.ImageView;
3196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport android.widget.LinearLayout;
3296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
3396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport java.util.ArrayList;
3496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
3596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell/**
3696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * @hide
3796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */
3896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellpublic class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView {
3996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private static final String TAG = "ActionMenuView";
40be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
41be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    // TODO Theme/style this.
42be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private static final int DIVIDER_PADDING = 12; // dips
4396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
4496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private MenuBuilder mMenu;
457ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
467ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    private int mMaxItems;
478028dd32a4a04154050220dd0693583d5b750330Adam Powell    private boolean mReserveOverflow;
488028dd32a4a04154050220dd0693583d5b750330Adam Powell    private OverflowMenuButton mOverflowButton;
496c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    private MenuPopupHelper mOverflowPopup;
50be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
51be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private float mButtonPaddingLeft;
52be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private float mButtonPaddingRight;
53be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private float mDividerPadding;
54be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
55be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private Drawable mDivider;
566c6f575423d6718c3ff322224c1520901ce881e1Adam Powell
576c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    private Runnable mShowOverflow = new Runnable() {
586c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        public void run() {
596c6f575423d6718c3ff322224c1520901ce881e1Adam Powell            showOverflowMenu();
606c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        }
616c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    };
6296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
638515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    private class OpenOverflowRunnable implements Runnable {
648515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        private MenuPopupHelper mPopup;
658515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
668515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        public OpenOverflowRunnable(MenuPopupHelper popup) {
678515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            mPopup = popup;
688515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        }
698515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
708515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        public void run() {
718515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            mOverflowPopup = mPopup;
728515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            mPopup.show();
738515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            mPostedOpenRunnable = null;
748515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        }
758515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
768515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
778515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    private OpenOverflowRunnable mPostedOpenRunnable;
788515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
7996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public ActionMenuView(Context context) {
8096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        this(context, null);
8196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
8296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
8396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public ActionMenuView(Context context, AttributeSet attrs) {
8496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        super(context, attrs);
857ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
86be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        final Resources res = getResources();
87773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
88773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell        // Measure for initial configuration
89be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        mMaxItems = getMaxActionButtons();
90773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
91773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell        // TODO There has to be a better way to indicate that we don't have a hard menu key.
92be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        final int screen = res.getConfiguration().screenLayout;
93773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell        mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
94773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell                Configuration.SCREENLAYOUT_SIZE_XLARGE;
95be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
96be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        TypedArray a = context.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
97be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        final int buttonStyle = a.getResourceId(
98be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell                com.android.internal.R.styleable.Theme_actionButtonStyle, 0);
99cf0357639e952a87f0d535c82691919af81f058bAdam Powell        mDivider = a.getDrawable(com.android.internal.R.styleable.Theme_dividerVertical);
100be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        a.recycle();
101be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
102be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        a = context.obtainStyledAttributes(buttonStyle, com.android.internal.R.styleable.View);
103be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        mButtonPaddingLeft = a.getDimension(com.android.internal.R.styleable.View_paddingLeft, 0);
104be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        mButtonPaddingRight = a.getDimension(com.android.internal.R.styleable.View_paddingRight, 0);
105be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        a.recycle();
106be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
107be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        mDividerPadding = DIVIDER_PADDING * res.getDisplayMetrics().density;
108f16888f1e849b0bc0b9c17e5f833c4e2cd54c382Adam Powell
109f16888f1e849b0bc0b9c17e5f833c4e2cd54c382Adam Powell        setBaselineAligned(false);
110773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    }
111773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
1126c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    @Override
113773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    public void onConfigurationChanged(Configuration newConfig) {
1148515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        super.onConfigurationChanged(newConfig);
115773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell        final int screen = newConfig.screenLayout;
116773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell        mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
117773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell                Configuration.SCREENLAYOUT_SIZE_XLARGE;
118be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        mMaxItems = getMaxActionButtons();
119773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell        if (mMenu != null) {
120773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell            mMenu.setMaxActionItems(mMaxItems);
121773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell            updateChildren(false);
122773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell        }
1236c6f575423d6718c3ff322224c1520901ce881e1Adam Powell
1246c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        if (mOverflowPopup != null && mOverflowPopup.isShowing()) {
1256c6f575423d6718c3ff322224c1520901ce881e1Adam Powell            mOverflowPopup.dismiss();
1266c6f575423d6718c3ff322224c1520901ce881e1Adam Powell            post(mShowOverflow);
1276c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        }
128773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    }
129773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
1308515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    @Override
1318515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    public void onDetachedFromWindow() {
1328515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        super.onDetachedFromWindow();
1338515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        if (mOverflowPopup != null && mOverflowPopup.isShowing()) {
1348515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            mOverflowPopup.dismiss();
1358515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        }
1368515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
1378515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
138be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private int getMaxActionButtons() {
139be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        return getResources().getInteger(com.android.internal.R.integer.max_action_buttons);
1408028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
1418028dd32a4a04154050220dd0693583d5b750330Adam Powell
1428028dd32a4a04154050220dd0693583d5b750330Adam Powell    public boolean isOverflowReserved() {
1438028dd32a4a04154050220dd0693583d5b750330Adam Powell        return mReserveOverflow;
1447ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
1457ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
146b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell    public void setOverflowReserved(boolean reserveOverflow) {
147b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell        mReserveOverflow = reserveOverflow;
148b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell    }
1497ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
1507ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    @Override
1517ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    protected LayoutParams generateDefaultLayoutParams() {
1527ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
1537ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell                LayoutParams.WRAP_CONTENT);
1546b336f835d637853800b94689375a03f337139a4Adam Powell        params.gravity = Gravity.CENTER_VERTICAL;
1557ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        return params;
1567ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
1577ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
1587ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    @Override
1597ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
1603f476b34049d062942eafcf48396f593e00bd324Adam Powell        if (p instanceof LayoutParams) {
1613f476b34049d062942eafcf48396f593e00bd324Adam Powell            LayoutParams result = new LayoutParams((LayoutParams) p);
1623f476b34049d062942eafcf48396f593e00bd324Adam Powell            if (result.gravity <= Gravity.NO_GRAVITY) {
1633f476b34049d062942eafcf48396f593e00bd324Adam Powell                result.gravity = Gravity.CENTER_VERTICAL;
1643f476b34049d062942eafcf48396f593e00bd324Adam Powell            }
1653f476b34049d062942eafcf48396f593e00bd324Adam Powell            return result;
1663f476b34049d062942eafcf48396f593e00bd324Adam Powell        }
1677ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        return generateDefaultLayoutParams();
1687ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
16996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
17096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public boolean invokeItem(MenuItemImpl item) {
17196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mMenu.performItemAction(item, 0);
17296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
17396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
17496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public int getWindowAnimations() {
17596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return 0;
17696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
17796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
17896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public void initialize(MenuBuilder menu, int menuType) {
1797ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        menu.setMaxActionItems(mMaxItems);
18096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mMenu = menu;
18196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        updateChildren(true);
18296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
18396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
18496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public void updateChildren(boolean cleared) {
1858028dd32a4a04154050220dd0693583d5b750330Adam Powell        final boolean reserveOverflow = mReserveOverflow;
18696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        removeAllViews();
18796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
1888028dd32a4a04154050220dd0693583d5b750330Adam Powell        final ArrayList<MenuItemImpl> itemsToShow = mMenu.getActionItems(reserveOverflow);
18996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        final int itemCount = itemsToShow.size();
19096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
191be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        boolean needsDivider = false;
19296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        for (int i = 0; i < itemCount; i++) {
193be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell            if (needsDivider) {
194be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell                addView(makeDividerView(), makeDividerLayoutParams());
195be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell            }
19696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell            final MenuItemImpl itemData = itemsToShow.get(i);
1973f476b34049d062942eafcf48396f593e00bd324Adam Powell            View actionView = itemData.getActionView();
1983f476b34049d062942eafcf48396f593e00bd324Adam Powell
1993f476b34049d062942eafcf48396f593e00bd324Adam Powell            if (actionView == null) {
2003f476b34049d062942eafcf48396f593e00bd324Adam Powell                // Check for a layout ID instead
2013f476b34049d062942eafcf48396f593e00bd324Adam Powell                final int layoutId = itemData.getActionViewId();
2023f476b34049d062942eafcf48396f593e00bd324Adam Powell                if (layoutId != 0) {
2033f476b34049d062942eafcf48396f593e00bd324Adam Powell                    LayoutInflater inflater = LayoutInflater.from(getContext());
2043f476b34049d062942eafcf48396f593e00bd324Adam Powell                    actionView = inflater.inflate(layoutId, this, false);
2053f476b34049d062942eafcf48396f593e00bd324Adam Powell                    itemData.setActionView(0);
2063f476b34049d062942eafcf48396f593e00bd324Adam Powell                    itemData.setActionView(actionView);
2073f476b34049d062942eafcf48396f593e00bd324Adam Powell                }
2083f476b34049d062942eafcf48396f593e00bd324Adam Powell            }
2093f476b34049d062942eafcf48396f593e00bd324Adam Powell
210cf78b3e5101349fdddbde14b3a55140f9562ae66Adam Powell            if (actionView != null) {
2119ab978713ce86fdaefed2407f4f3c998ab0e3178Adam Powell                final ViewParent parent = actionView.getParent();
2129ab978713ce86fdaefed2407f4f3c998ab0e3178Adam Powell                if (parent instanceof ViewGroup) {
2139ab978713ce86fdaefed2407f4f3c998ab0e3178Adam Powell                    ((ViewGroup) parent).removeView(actionView);
2149ab978713ce86fdaefed2407f4f3c998ab0e3178Adam Powell                }
2153f476b34049d062942eafcf48396f593e00bd324Adam Powell                addView(actionView, makeActionViewLayoutParams(actionView));
216cf78b3e5101349fdddbde14b3a55140f9562ae66Adam Powell            } else {
217be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell                needsDivider = addItemView(i == 0 || !needsDivider,
218be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell                        (ActionMenuItemView) itemData.getItemView(
219be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell                                MenuBuilder.TYPE_ACTION_BUTTON, this));
220cf78b3e5101349fdddbde14b3a55140f9562ae66Adam Powell            }
22196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        }
2228028dd32a4a04154050220dd0693583d5b750330Adam Powell
2238028dd32a4a04154050220dd0693583d5b750330Adam Powell        if (reserveOverflow) {
2248028dd32a4a04154050220dd0693583d5b750330Adam Powell            if (mMenu.getNonActionItems(true).size() > 0) {
2258028dd32a4a04154050220dd0693583d5b750330Adam Powell                OverflowMenuButton button = new OverflowMenuButton(mContext);
2268028dd32a4a04154050220dd0693583d5b750330Adam Powell                addView(button);
2278028dd32a4a04154050220dd0693583d5b750330Adam Powell                mOverflowButton = button;
2288028dd32a4a04154050220dd0693583d5b750330Adam Powell            } else {
2298028dd32a4a04154050220dd0693583d5b750330Adam Powell                mOverflowButton = null;
2308028dd32a4a04154050220dd0693583d5b750330Adam Powell            }
2318028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
2328028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
2338028dd32a4a04154050220dd0693583d5b750330Adam Powell
2348028dd32a4a04154050220dd0693583d5b750330Adam Powell    public boolean showOverflowMenu() {
2358515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        if (mOverflowButton != null && !isOverflowMenuShowing()) {
2368515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            mMenu.getCallback().onMenuModeChange(mMenu);
237f75eeb28def26798682748aa5dedabebac86bb6aAdam Powell            return true;
238f75eeb28def26798682748aa5dedabebac86bb6aAdam Powell        }
239f75eeb28def26798682748aa5dedabebac86bb6aAdam Powell        return false;
240f75eeb28def26798682748aa5dedabebac86bb6aAdam Powell    }
241f75eeb28def26798682748aa5dedabebac86bb6aAdam Powell
2428515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    public void openOverflowMenu() {
2438515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        OverflowPopup popup = new OverflowPopup(getContext(), mMenu, mOverflowButton, true);
2448515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        mPostedOpenRunnable = new OpenOverflowRunnable(popup);
2458515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        // Post this for later; we might still need a layout for the anchor to be right.
2468515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        post(mPostedOpenRunnable);
2478515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
2488515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
249f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell    public boolean isOverflowMenuShowing() {
2508515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        return mOverflowPopup != null && mOverflowPopup.isShowing();
2518515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
2528515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
2538515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    public boolean isOverflowMenuOpen() {
2548515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        return mOverflowPopup != null;
255f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell    }
256f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell
257f75eeb28def26798682748aa5dedabebac86bb6aAdam Powell    public boolean hideOverflowMenu() {
2588515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        if (mPostedOpenRunnable != null) {
2598515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            removeCallbacks(mPostedOpenRunnable);
2608515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            return true;
2618515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        }
2628515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
2636c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        MenuPopupHelper popup = mOverflowPopup;
264f75eeb28def26798682748aa5dedabebac86bb6aAdam Powell        if (popup != null) {
265f75eeb28def26798682748aa5dedabebac86bb6aAdam Powell            popup.dismiss();
2668028dd32a4a04154050220dd0693583d5b750330Adam Powell            return true;
2678028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
2688028dd32a4a04154050220dd0693583d5b750330Adam Powell        return false;
26996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
27096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
271be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private boolean addItemView(boolean needsDivider, ActionMenuItemView view) {
27296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        view.setItemInvoker(this);
273be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        boolean hasText = view.hasText();
274be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
275be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        if (hasText && needsDivider) {
276be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell            addView(makeDividerView(), makeDividerLayoutParams());
277be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        }
27896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        addView(view);
279be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        return hasText;
280be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    }
281be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
282be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private ImageView makeDividerView() {
283be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        ImageView result = new ImageView(mContext);
284be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        result.setImageDrawable(mDivider);
285be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        result.setScaleType(ImageView.ScaleType.FIT_XY);
286be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        return result;
287be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    }
288be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
289be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    private LayoutParams makeDividerLayoutParams() {
290be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
291be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell                LayoutParams.MATCH_PARENT);
292be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        params.topMargin = (int) mDividerPadding;
293be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        params.bottomMargin = (int) mDividerPadding;
294be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        return params;
295be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    }
296be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
2973f476b34049d062942eafcf48396f593e00bd324Adam Powell    private LayoutParams makeActionViewLayoutParams(View view) {
2983f476b34049d062942eafcf48396f593e00bd324Adam Powell        LayoutParams params = generateLayoutParams(view.getLayoutParams());
299be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        params.leftMargin = (int) mButtonPaddingLeft;
300be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        params.rightMargin = (int) mButtonPaddingRight;
301be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        return params;
30296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
3038028dd32a4a04154050220dd0693583d5b750330Adam Powell
3048028dd32a4a04154050220dd0693583d5b750330Adam Powell    private class OverflowMenuButton extends ImageButton {
3058028dd32a4a04154050220dd0693583d5b750330Adam Powell        public OverflowMenuButton(Context context) {
306079fd1c0a329b0fbd3761abe2e900a941131efedAdam Powell            super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
3078028dd32a4a04154050220dd0693583d5b750330Adam Powell
3088028dd32a4a04154050220dd0693583d5b750330Adam Powell            setClickable(true);
3098028dd32a4a04154050220dd0693583d5b750330Adam Powell            setFocusable(true);
3108028dd32a4a04154050220dd0693583d5b750330Adam Powell            setVisibility(VISIBLE);
3118028dd32a4a04154050220dd0693583d5b750330Adam Powell            setEnabled(true);
3128028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
3138028dd32a4a04154050220dd0693583d5b750330Adam Powell
3148028dd32a4a04154050220dd0693583d5b750330Adam Powell        @Override
3158028dd32a4a04154050220dd0693583d5b750330Adam Powell        public boolean performClick() {
3168028dd32a4a04154050220dd0693583d5b750330Adam Powell            if (super.performClick()) {
3178028dd32a4a04154050220dd0693583d5b750330Adam Powell                return true;
3188028dd32a4a04154050220dd0693583d5b750330Adam Powell            }
3198028dd32a4a04154050220dd0693583d5b750330Adam Powell
3208515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            showOverflowMenu();
3218028dd32a4a04154050220dd0693583d5b750330Adam Powell            return true;
3228028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
3238028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
3248515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
3258515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    private class OverflowPopup extends MenuPopupHelper {
3268515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
3278515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell                boolean overflowOnly) {
3288515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            super(context, menu, anchorView, overflowOnly);
3298515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        }
3308515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
3318515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        @Override
3328515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        public void onDismiss() {
3338515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            super.onDismiss();
3348515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            mMenu.getCallback().onCloseMenu(mMenu, true);
3358515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell            mOverflowPopup = null;
3368515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        }
3378515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
33896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell}
339