1bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/*
2bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Copyright (C) 2010 The Android Open Source Project
3bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell *
4bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Licensed under the Apache License, Version 2.0 (the "License");
5bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * you may not use this file except in compliance with the License.
6bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * You may obtain a copy of the License at
7bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell *
8bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell *      http://www.apache.org/licenses/LICENSE-2.0
9bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell *
10bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Unless required by applicable law or agreed to in writing, software
11bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * distributed under the License is distributed on an "AS IS" BASIS,
12bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * See the License for the specific language governing permissions and
14bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * limitations under the License.
15bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
16bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
17da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.view.menu;
18bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
19bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Context;
20bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.Resources;
21bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.os.Parcelable;
22da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
23da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.internal.widget.ListPopupWindow;
24bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.KeyEvent;
25bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.LayoutInflater;
2630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
27bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View;
28bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View.MeasureSpec;
29bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewGroup;
30bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewTreeObserver;
31bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.AdapterView;
32bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.BaseAdapter;
33bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.FrameLayout;
34bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.ListAdapter;
35bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.PopupWindow;
36bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
37bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList;
38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
39bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/**
40bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Presents a menu as a small, simple popup anchored to another view.
41ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani *
42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * @hide
43bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
44bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellpublic class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener,
4520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener,
4620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        MenuPresenter {
4720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
48ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String TAG = "MenuPopupHelper";
49bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
50ee7c9fb199e9b9af8d40a1f9e27d85465acf8301Chris Banes    static final int ITEM_LAYOUT = R.layout.abc_popup_menu_item_layout;
51bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
52ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private Context mContext;
53ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private LayoutInflater mInflater;
54ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ListPopupWindow mPopup;
55ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuBuilder mMenu;
56ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private int mPopupMaxWidth;
57ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private View mAnchorView;
58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mOverflowOnly;
59ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ViewTreeObserver mTreeObserver;
60bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuAdapter mAdapter;
62bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
63ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private Callback mPresenterCallback;
64bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean mForceShowIcon;
66bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ViewGroup mMeasureParent;
68bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuPopupHelper(Context context, MenuBuilder menu) {
70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        this(context, menu, null, false);
71ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
72bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
73ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) {
74ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        this(context, menu, anchorView, false);
75ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
76bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
77ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuPopupHelper(Context context, MenuBuilder menu,
7820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            View anchorView, boolean overflowOnly) {
79ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mContext = context;
80ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mInflater = LayoutInflater.from(context);
81ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mMenu = menu;
82ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mOverflowOnly = overflowOnly;
83bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
84ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Resources res = context.getResources();
85ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2,
8607a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes                res.getDimensionPixelSize(R.dimen.abc_config_prefDialogWidth));
87bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
88ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mAnchorView = anchorView;
89bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
90ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        menu.addMenuPresenter(this);
91ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
92bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
93ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setAnchorView(View anchor) {
94ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mAnchorView = anchor;
95ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
96bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
97ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setForceShowIcon(boolean forceShow) {
98ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mForceShowIcon = forceShow;
99bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void show() {
102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!tryShow()) {
103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
105bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
106bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean tryShow() {
108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup = new ListPopupWindow(mContext, null, R.attr.popupMenuStyle);
109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setOnDismissListener(this);
110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setOnItemClickListener(this);
111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mAdapter = new MenuAdapter(mMenu);
113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setAdapter(mAdapter);
114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setModal(true);
115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        View anchor = mAnchorView;
117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (anchor != null) {
118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final boolean addGlobalListener = mTreeObserver == null;
119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest
12020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (addGlobalListener) {
12120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mTreeObserver.addOnGlobalLayoutListener(this);
12220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPopup.setAnchorView(anchor);
124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
125ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return false;
126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
127bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setContentWidth(Math.min(measureContentWidth(mAdapter), mPopupMaxWidth));
129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.show();
131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.getListView().setOnKeyListener(this);
132ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return true;
133bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void dismiss() {
136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (isShowing()) {
137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPopup.dismiss();
138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
139bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onDismiss() {
142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup = null;
143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mMenu.close();
144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mTreeObserver != null) {
14520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            if (!mTreeObserver.isAlive()) {
14620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                mTreeObserver = mAnchorView.getViewTreeObserver();
14720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            }
148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mTreeObserver.removeGlobalOnLayoutListener(this);
149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mTreeObserver = null;
150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
151bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShowing() {
154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mPopup != null && mPopup.isShowing();
155bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
156bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuAdapter adapter = mAdapter;
160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0);
161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
162bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean onKey(View v, int keyCode, KeyEvent event) {
164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) {
165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            dismiss();
166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return true;
167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
169bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private int measureContentWidth(ListAdapter adapter) {
172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Menus don't tend to be long, so this is more sane than it looks.
173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        int width = 0;
174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        View itemView = null;
175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        int itemType = 0;
176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int widthMeasureSpec =
17720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int heightMeasureSpec =
17920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int count = adapter.getCount();
181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < count; i++) {
182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int positionType = adapter.getItemViewType(i);
183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (positionType != itemType) {
184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemType = positionType;
185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemView = null;
186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mMeasureParent == null) {
188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mMeasureParent = new FrameLayout(mContext);
189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            itemView = adapter.getView(i, itemView, mMeasureParent);
191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            itemView.measure(widthMeasureSpec, heightMeasureSpec);
192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            width = Math.max(width, itemView.getMeasuredWidth());
193bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return width;
195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
196bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onGlobalLayout() {
199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (isShowing()) {
200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final View anchor = mAnchorView;
201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (anchor == null || !anchor.isShown()) {
202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                dismiss();
203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (isShowing()) {
204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Recompute window size and position
205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPopup.show();
206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
207bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
208bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
209bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void initForMenu(Context context, MenuBuilder menu) {
212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Don't need to do anything; we added as a presenter in the constructor.
213bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
214bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuView getMenuView(ViewGroup root) {
217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        throw new UnsupportedOperationException("MenuPopupHelpers manage their own views");
218bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
219bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void updateMenuView(boolean cleared) {
22220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mAdapter != null) {
22320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mAdapter.notifyDataSetChanged();
22420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
225bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
226bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCallback(Callback cb) {
229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPresenterCallback = cb;
230bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
231bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (subMenu.hasVisibleItems()) {
235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false);
236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            subPopup.setCallback(mPresenterCallback);
237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            boolean preserveIconSpacing = false;
239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int count = subMenu.size();
240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            for (int i = 0; i < count; i++) {
241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItem childItem = subMenu.getItem(i);
242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (childItem.isVisible() && childItem.getIcon() != null) {
243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    preserveIconSpacing = true;
244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    break;
245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            subPopup.setForceShowIcon(preserveIconSpacing);
248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (subPopup.tryShow()) {
250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (mPresenterCallback != null) {
251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mPresenterCallback.onOpenSubMenu(subMenu);
252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return true;
254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
257bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
258bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Only care about the (sub)menu we're presenting.
26220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (menu != mMenu) {
26320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            return;
26420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dismiss();
267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mPresenterCallback != null) {
268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPresenterCallback.onCloseMenu(menu, allMenusAreClosing);
269bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
270bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
271bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
272bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    @Override
273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean flagActionItems() {
274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int getId() {
287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return 0;
288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Parcelable onSaveInstanceState() {
292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onRestoreInstanceState(Parcelable state) {
297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private class MenuAdapter extends BaseAdapter {
30020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        private MenuBuilder mAdapterMenu;
302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        private int mExpandedIndex = -1;
303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public MenuAdapter(MenuBuilder menu) {
305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mAdapterMenu = menu;
306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            findExpandedIndex();
307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public int getCount() {
310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            ArrayList<MenuItemImpl> items = mOverflowOnly ?
31120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mExpandedIndex < 0) {
313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return items.size();
314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.size() - 1;
316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public MenuItemImpl getItem(int position) {
319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            ArrayList<MenuItemImpl> items = mOverflowOnly ?
32020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                position++;
323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.get(position);
325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public long getItemId(int position) {
328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Since a menu item's ID is optional, we'll use the position as an
329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // ID for the item in the AdapterView
330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return position;
331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public View getView(int position, View convertView, ViewGroup parent) {
334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (convertView == null) {
335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                convertView = mInflater.inflate(ITEM_LAYOUT, parent, false);
336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuView.ItemView itemView = (MenuView.ItemView) convertView;
339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mForceShowIcon) {
340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                ((ListMenuItemView) convertView).setForceShowIcon(true);
341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            itemView.initialize(getItem(position), 0);
343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return convertView;
344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        void findExpandedIndex() {
347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl expandedItem = mMenu.getExpandedItem();
348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (expandedItem != null) {
349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int count = items.size();
351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                for (int i = 0; i < count; i++) {
352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    final MenuItemImpl item = items.get(i);
353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (item == expandedItem) {
354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        mExpandedIndex = i;
355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        return;
356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedIndex = -1;
360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        @Override
363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public void notifyDataSetChanged() {
364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            findExpandedIndex();
365ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            super.notifyDataSetChanged();
366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
367bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
368bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell}
369ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
370