14267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell/*
24267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * Copyright (C) 2010 The Android Open Source Project
34267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell *
44267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
54267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * you may not use this file except in compliance with the License.
64267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * You may obtain a copy of the License at
74267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell *
84267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
94267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell *
104267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * Unless required by applicable law or agreed to in writing, software
114267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
124267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * See the License for the specific language governing permissions and
144267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * limitations under the License.
154267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell */
164267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
174267534d1c42af847ed0cefd1c88c99f66b36571Adam Powellpackage com.android.internal.view.menu;
184267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
194267534d1c42af847ed0cefd1c88c99f66b36571Adam Powellimport android.content.Context;
2038639b1d75933bfb720db79fce26f09478709614Adam Powellimport android.content.res.Resources;
2111ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powellimport android.os.Parcelable;
2254c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powellimport android.view.Gravity;
238028dd32a4a04154050220dd0693583d5b750330Adam Powellimport android.view.KeyEvent;
24696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.view.LayoutInflater;
259151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powellimport android.view.MenuItem;
2680e72700858eb58b379f77a0da5fd3a98e1aa07cAlan Viveretteimport android.view.MotionEvent;
274267534d1c42af847ed0cefd1c88c99f66b36571Adam Powellimport android.view.View;
284267534d1c42af847ed0cefd1c88c99f66b36571Adam Powellimport android.view.View.MeasureSpec;
29696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.view.ViewGroup;
300458796f1401732b38660794148f4c5e5602f432Adam Powellimport android.view.ViewTreeObserver;
314267534d1c42af847ed0cefd1c88c99f66b36571Adam Powellimport android.widget.AdapterView;
32696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.widget.BaseAdapter;
339151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powellimport android.widget.FrameLayout;
34696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport android.widget.ListAdapter;
354267534d1c42af847ed0cefd1c88c99f66b36571Adam Powellimport android.widget.ListPopupWindow;
366c6f575423d6718c3ff322224c1520901ce881e1Adam Powellimport android.widget.PopupWindow;
374267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
38696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellimport java.util.ArrayList;
398028dd32a4a04154050220dd0693583d5b750330Adam Powell
404267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell/**
41696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell * Presents a menu as a small, simple popup anchored to another view.
424267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell * @hide
434267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell */
440458796f1401732b38660794148f4c5e5602f432Adam Powellpublic class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener,
454afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener,
46696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        View.OnAttachStateChangeListener, MenuPresenter {
474267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    private static final String TAG = "MenuPopupHelper";
484267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
49696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    static final int ITEM_LAYOUT = com.android.internal.R.layout.popup_menu_item_layout;
50696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
510bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private final Context mContext;
520bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private final LayoutInflater mInflater;
530bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private final MenuBuilder mMenu;
540bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private final MenuAdapter mAdapter;
550bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private final boolean mOverflowOnly;
560bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private final int mPopupMaxWidth;
570bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
584afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell    private View mAnchorView;
590bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private ListPopupWindow mPopup;
600458796f1401732b38660794148f4c5e5602f432Adam Powell    private ViewTreeObserver mTreeObserver;
61696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private Callback mPresenterCallback;
62e2b03a62e5014ea60e24a989544fa549b493a520Adam Powell
639151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell    boolean mForceShowIcon;
649151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell
659151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell    private ViewGroup mMeasureParent;
669151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell
670bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    /** Whether the cached content width value is valid. */
680bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private boolean mHasContentWidth;
690bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
700bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    /** Cached content width from {@link #measureContentWidth}. */
710bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private int mContentWidth;
720bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
7354c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    private int mDropDownGravity = Gravity.NO_GRAVITY;
7454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
758028dd32a4a04154050220dd0693583d5b750330Adam Powell    public MenuPopupHelper(Context context, MenuBuilder menu) {
768028dd32a4a04154050220dd0693583d5b750330Adam Powell        this(context, menu, null, false);
778028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
784267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
798028dd32a4a04154050220dd0693583d5b750330Adam Powell    public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) {
808028dd32a4a04154050220dd0693583d5b750330Adam Powell        this(context, menu, anchorView, false);
818028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
828028dd32a4a04154050220dd0693583d5b750330Adam Powell
838028dd32a4a04154050220dd0693583d5b750330Adam Powell    public MenuPopupHelper(Context context, MenuBuilder menu,
848028dd32a4a04154050220dd0693583d5b750330Adam Powell            View anchorView, boolean overflowOnly) {
854267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        mContext = context;
86696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mInflater = LayoutInflater.from(context);
878028dd32a4a04154050220dd0693583d5b750330Adam Powell        mMenu = menu;
880bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        mAdapter = new MenuAdapter(mMenu);
898028dd32a4a04154050220dd0693583d5b750330Adam Powell        mOverflowOnly = overflowOnly;
904267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
9138639b1d75933bfb720db79fce26f09478709614Adam Powell        final Resources res = context.getResources();
9238639b1d75933bfb720db79fce26f09478709614Adam Powell        mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2,
9338639b1d75933bfb720db79fce26f09478709614Adam Powell                res.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
948028dd32a4a04154050220dd0693583d5b750330Adam Powell
954afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        mAnchorView = anchorView;
96696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
97696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        menu.addMenuPresenter(this);
984267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    }
994267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
100f0ad6e6eaf48ac8f4007232ad0a8511a7b5cfc0eAdam Powell    public void setAnchorView(View anchor) {
1014afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        mAnchorView = anchor;
102f0ad6e6eaf48ac8f4007232ad0a8511a7b5cfc0eAdam Powell    }
103f0ad6e6eaf48ac8f4007232ad0a8511a7b5cfc0eAdam Powell
1049151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell    public void setForceShowIcon(boolean forceShow) {
1059151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell        mForceShowIcon = forceShow;
1069151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell    }
1079151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell
10854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    public void setGravity(int gravity) {
10954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        mDropDownGravity = gravity;
11054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    }
11154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
1124267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public void show() {
1135e3f284baa271cb0fbf90e504d19fdd2e385382eAdam Powell        if (!tryShow()) {
1145e3f284baa271cb0fbf90e504d19fdd2e385382eAdam Powell            throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
1155e3f284baa271cb0fbf90e504d19fdd2e385382eAdam Powell        }
1165e3f284baa271cb0fbf90e504d19fdd2e385382eAdam Powell    }
1175e3f284baa271cb0fbf90e504d19fdd2e385382eAdam Powell
118ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette    public ListPopupWindow getPopup() {
119ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        return mPopup;
120ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette    }
121ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1225e3f284baa271cb0fbf90e504d19fdd2e385382eAdam Powell    public boolean tryShow() {
1230b2d306e7000f4c0c6ad4e00d494bb401d8a9fc2Adam Powell        mPopup = new ListPopupWindow(mContext, null, com.android.internal.R.attr.popupMenuStyle);
1248515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        mPopup.setOnDismissListener(this);
125696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPopup.setOnItemClickListener(this);
126696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPopup.setAdapter(mAdapter);
1274267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        mPopup.setModal(true);
1284267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
1294afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        View anchor = mAnchorView;
1300458796f1401732b38660794148f4c5e5602f432Adam Powell        if (anchor != null) {
1314afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            final boolean addGlobalListener = mTreeObserver == null;
1324afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest
1334afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this);
1344afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            anchor.addOnAttachStateChangeListener(this);
1350458796f1401732b38660794148f4c5e5602f432Adam Powell            mPopup.setAnchorView(anchor);
13654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell            mPopup.setDropDownGravity(mDropDownGravity);
1374be0d52125b88dc992a4c500edbe95bf55484e0bAdam Powell        } else {
1385e3f284baa271cb0fbf90e504d19fdd2e385382eAdam Powell            return false;
1398028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
1404267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
1410bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        if (!mHasContentWidth) {
1420bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette            mContentWidth = measureContentWidth();
1430bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette            mHasContentWidth = true;
1440bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        }
1450bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
1460bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        mPopup.setContentWidth(mContentWidth);
147aa0b92ce2b51987e9c864164234fe968ab5b9311Adam Powell        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
1484267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        mPopup.show();
1498028dd32a4a04154050220dd0693583d5b750330Adam Powell        mPopup.getListView().setOnKeyListener(this);
1505e3f284baa271cb0fbf90e504d19fdd2e385382eAdam Powell        return true;
1514267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    }
1524267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
1534267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public void dismiss() {
1543d3da27ab394108fd51771616cca3279baae99d1Adam Powell        if (isShowing()) {
1553d3da27ab394108fd51771616cca3279baae99d1Adam Powell            mPopup.dismiss();
1563d3da27ab394108fd51771616cca3279baae99d1Adam Powell        }
1578515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
1588515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
1598515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    public void onDismiss() {
1608515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        mPopup = null;
16142b91bbcdaf64b2f19d0a9ce168964b31a5dc139Adam Powell        mMenu.close();
1624afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        if (mTreeObserver != null) {
1634afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver();
164ca51e8788a58f2af3525b7214a675f2d0233e5daAdam Powell            mTreeObserver.removeGlobalOnLayoutListener(this);
1654afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            mTreeObserver = null;
166ed8b403cc8066bf76cdf98f8d9906ff810defc5bAdam Powell        }
1674afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        mAnchorView.removeOnAttachStateChangeListener(this);
1684267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    }
1694267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
1708028dd32a4a04154050220dd0693583d5b750330Adam Powell    public boolean isShowing() {
1718028dd32a4a04154050220dd0693583d5b750330Adam Powell        return mPopup != null && mPopup.isShowing();
1728028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
1738028dd32a4a04154050220dd0693583d5b750330Adam Powell
174696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
1754267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
176696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        MenuAdapter adapter = mAdapter;
177696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0);
1784267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    }
1794267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
1808028dd32a4a04154050220dd0693583d5b750330Adam Powell    public boolean onKey(View v, int keyCode, KeyEvent event) {
1818028dd32a4a04154050220dd0693583d5b750330Adam Powell        if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) {
1828028dd32a4a04154050220dd0693583d5b750330Adam Powell            dismiss();
1838028dd32a4a04154050220dd0693583d5b750330Adam Powell            return true;
1848028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
1858028dd32a4a04154050220dd0693583d5b750330Adam Powell        return false;
1868028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
1878028dd32a4a04154050220dd0693583d5b750330Adam Powell
1880bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette    private int measureContentWidth() {
1894267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        // Menus don't tend to be long, so this is more sane than it looks.
1900bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        int maxWidth = 0;
1914267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        View itemView = null;
19250f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell        int itemType = 0;
1930bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
1940bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        final ListAdapter adapter = mAdapter;
1950bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
1960bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
1974267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        final int count = adapter.getCount();
1984267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        for (int i = 0; i < count; i++) {
19950f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell            final int positionType = adapter.getItemViewType(i);
20050f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell            if (positionType != itemType) {
20150f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell                itemType = positionType;
20250f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell                itemView = null;
20350f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell            }
2040bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
2059151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            if (mMeasureParent == null) {
2069151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                mMeasureParent = new FrameLayout(mContext);
2079151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            }
2080bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
2099151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            itemView = adapter.getView(i, itemView, mMeasureParent);
2104267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell            itemView.measure(widthMeasureSpec, heightMeasureSpec);
2110bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
2120bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette            final int itemWidth = itemView.getMeasuredWidth();
2130bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette            if (itemWidth >= mPopupMaxWidth) {
2140bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette                return mPopupMaxWidth;
2150bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette            } else if (itemWidth > maxWidth) {
2160bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette                maxWidth = itemWidth;
2170bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette            }
2184267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        }
2190bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
2200bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        return maxWidth;
2214267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    }
2220458796f1401732b38660794148f4c5e5602f432Adam Powell
2230458796f1401732b38660794148f4c5e5602f432Adam Powell    @Override
2240458796f1401732b38660794148f4c5e5602f432Adam Powell    public void onGlobalLayout() {
2254afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        if (isShowing()) {
2264afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            final View anchor = mAnchorView;
227ca51e8788a58f2af3525b7214a675f2d0233e5daAdam Powell            if (anchor == null || !anchor.isShown()) {
2280458796f1401732b38660794148f4c5e5602f432Adam Powell                dismiss();
229ca51e8788a58f2af3525b7214a675f2d0233e5daAdam Powell            } else if (isShowing()) {
230aa0b92ce2b51987e9c864164234fe968ab5b9311Adam Powell                // Recompute window size and position
231aa0b92ce2b51987e9c864164234fe968ab5b9311Adam Powell                mPopup.show();
2320458796f1401732b38660794148f4c5e5602f432Adam Powell            }
2330458796f1401732b38660794148f4c5e5602f432Adam Powell        }
2340458796f1401732b38660794148f4c5e5602f432Adam Powell    }
2354afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell
2364afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell    @Override
2374afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell    public void onViewAttachedToWindow(View v) {
2384afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell    }
2394afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell
2404afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell    @Override
2414afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell    public void onViewDetachedFromWindow(View v) {
2424afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        if (mTreeObserver != null) {
2434afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            if (!mTreeObserver.isAlive()) mTreeObserver = v.getViewTreeObserver();
2444afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell            mTreeObserver.removeGlobalOnLayoutListener(this);
2454afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        }
2464afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell        v.removeOnAttachStateChangeListener(this);
2474afd62b18c52a55371ab923d54f93615ad68fd7aAdam Powell    }
248696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
249696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
250696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void initForMenu(Context context, MenuBuilder menu) {
251696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        // Don't need to do anything; we added as a presenter in the constructor.
252696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
253696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
254696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
255696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public MenuView getMenuView(ViewGroup root) {
256696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        throw new UnsupportedOperationException("MenuPopupHelpers manage their own views");
257696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
258696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
259696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
260696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void updateMenuView(boolean cleared) {
2610bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        mHasContentWidth = false;
2620bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette
2630bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        if (mAdapter != null) {
2640bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette            mAdapter.notifyDataSetChanged();
2650bce6ab8cd8aadc9784dda2f3f4cc9dd91b796c7Alan Viverette        }
266696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
267696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
268696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
269696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void setCallback(Callback cb) {
270696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenterCallback = cb;
271696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
272696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
273696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
274696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
275696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (subMenu.hasVisibleItems()) {
276696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false);
277696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            subPopup.setCallback(mPresenterCallback);
2789151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell
2799151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            boolean preserveIconSpacing = false;
2809151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            final int count = subMenu.size();
2819151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            for (int i = 0; i < count; i++) {
2829151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                MenuItem childItem = subMenu.getItem(i);
2839151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                if (childItem.isVisible() && childItem.getIcon() != null) {
2849151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                    preserveIconSpacing = true;
2859151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                    break;
2869151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                }
2879151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            }
2889151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            subPopup.setForceShowIcon(preserveIconSpacing);
2899151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell
290696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (subPopup.tryShow()) {
291696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                if (mPresenterCallback != null) {
292696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    mPresenterCallback.onOpenSubMenu(subMenu);
293696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                }
294696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                return true;
295696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
296696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
297696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return false;
298696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
299696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
300696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
301696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
302696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        // Only care about the (sub)menu we're presenting.
303696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (menu != mMenu) return;
304696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
305696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        dismiss();
306696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mPresenterCallback != null) {
307696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPresenterCallback.onCloseMenu(menu, allMenusAreClosing);
308696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
309696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
310696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
311696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
312696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean flagActionItems() {
313696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return false;
314696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
315696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
3168d02deabac62c4a68a335a7b3141795466362b89Adam Powell    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
3178d02deabac62c4a68a335a7b3141795466362b89Adam Powell        return false;
3188d02deabac62c4a68a335a7b3141795466362b89Adam Powell    }
3198d02deabac62c4a68a335a7b3141795466362b89Adam Powell
3208d02deabac62c4a68a335a7b3141795466362b89Adam Powell    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
3218d02deabac62c4a68a335a7b3141795466362b89Adam Powell        return false;
3228d02deabac62c4a68a335a7b3141795466362b89Adam Powell    }
3238d02deabac62c4a68a335a7b3141795466362b89Adam Powell
324275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    @Override
325275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    public int getId() {
326275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        return 0;
327275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    }
328275702c2f47ed87ab642462530092d9777f32ecdAdam Powell
329275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    @Override
330275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    public Parcelable onSaveInstanceState() {
331275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        return null;
332275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    }
333275702c2f47ed87ab642462530092d9777f32ecdAdam Powell
334275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    @Override
335275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    public void onRestoreInstanceState(Parcelable state) {
336275702c2f47ed87ab642462530092d9777f32ecdAdam Powell    }
337275702c2f47ed87ab642462530092d9777f32ecdAdam Powell
338696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private class MenuAdapter extends BaseAdapter {
339696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        private MenuBuilder mAdapterMenu;
340275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        private int mExpandedIndex = -1;
341696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
342696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public MenuAdapter(MenuBuilder menu) {
343696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mAdapterMenu = menu;
344275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            findExpandedIndex();
345696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
346696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
347696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public int getCount() {
348696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            ArrayList<MenuItemImpl> items = mOverflowOnly ?
349696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
350275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            if (mExpandedIndex < 0) {
351275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                return items.size();
352275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            }
353275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            return items.size() - 1;
354696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
355696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
356696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public MenuItemImpl getItem(int position) {
357696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            ArrayList<MenuItemImpl> items = mOverflowOnly ?
358696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                    mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
359275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
360275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                position++;
361275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            }
362696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return items.get(position);
363696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
364696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
365696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public long getItemId(int position) {
366696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            // Since a menu item's ID is optional, we'll use the position as an
367696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            // ID for the item in the AdapterView
368696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return position;
369696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
370696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
371696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public View getView(int position, View convertView, ViewGroup parent) {
372696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            if (convertView == null) {
373696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                convertView = mInflater.inflate(ITEM_LAYOUT, parent, false);
374696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            }
375696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
376696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            MenuView.ItemView itemView = (MenuView.ItemView) convertView;
3779151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            if (mForceShowIcon) {
3789151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell                ((ListMenuItemView) convertView).setForceShowIcon(true);
3799151103ff20d28e8db2a2cc0386d57b8dad4b5d5Adam Powell            }
380696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            itemView.initialize(getItem(position), 0);
381696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            return convertView;
382696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
38311ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
384275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        void findExpandedIndex() {
385275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            final MenuItemImpl expandedItem = mMenu.getExpandedItem();
386275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            if (expandedItem != null) {
387275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
388275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                final int count = items.size();
389275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                for (int i = 0; i < count; i++) {
390275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                    final MenuItemImpl item = items.get(i);
391275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                    if (item == expandedItem) {
392275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                        mExpandedIndex = i;
393275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                        return;
394275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                    }
395275702c2f47ed87ab642462530092d9777f32ecdAdam Powell                }
396275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            }
397275702c2f47ed87ab642462530092d9777f32ecdAdam Powell            mExpandedIndex = -1;
398275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        }
39911ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell
400275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        @Override
40176889f3482d6391b17f0961f7356c1e8169c8813Adam Powell        public void notifyDataSetChanged() {
40276889f3482d6391b17f0961f7356c1e8169c8813Adam Powell            findExpandedIndex();
40376889f3482d6391b17f0961f7356c1e8169c8813Adam Powell            super.notifyDataSetChanged();
404275702c2f47ed87ab642462530092d9777f32ecdAdam Powell        }
40511ed1d6cae9214335c92ac38498a4e6c7d1c8324Adam Powell    }
4064267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell}
407