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;
2349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.ListPopupWindow;
2449c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.Gravity;
25bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.KeyEvent;
26bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.LayoutInflater;
2730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
28bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View;
29bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View.MeasureSpec;
30bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewGroup;
31bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewTreeObserver;
32bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.AdapterView;
33bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.BaseAdapter;
34bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.FrameLayout;
35bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.ListAdapter;
36bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.PopupWindow;
37bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList;
39bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
40bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/**
41bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Presents a menu as a small, simple popup anchored to another view.
42ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani *
43bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * @hide
44bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
45bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellpublic class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener,
4620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener,
4720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        MenuPresenter {
4820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
49ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String TAG = "MenuPopupHelper";
50bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
51ee7c9fb199e9b9af8d40a1f9e27d85465acf8301Chris Banes    static final int ITEM_LAYOUT = R.layout.abc_popup_menu_item_layout;
52bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
5349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private final Context mContext;
5449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private final LayoutInflater mInflater;
5549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private final MenuBuilder mMenu;
5649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private final MenuAdapter mAdapter;
5749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private final boolean mOverflowOnly;
5849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private final int mPopupMaxWidth;
5949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private final int mPopupStyleAttr;
6049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private View mAnchorView;
6249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private ListPopupWindow mPopup;
63ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ViewTreeObserver mTreeObserver;
64ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private Callback mPresenterCallback;
65bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
66ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    boolean mForceShowIcon;
67bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
68ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private ViewGroup mMeasureParent;
69bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
7049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /** Whether the cached content width value is valid. */
7149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private boolean mHasContentWidth;
7249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
7349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /** Cached content width from {@link #measureContentWidth}. */
7449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private int mContentWidth;
7549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
7649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private int mDropDownGravity = Gravity.NO_GRAVITY;
7749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
78ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuPopupHelper(Context context, MenuBuilder menu) {
7949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        this(context, menu, null, false, R.attr.popupMenuStyle);
80ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
81bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
82ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) {
8349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        this(context, menu, anchorView, false, R.attr.popupMenuStyle);
84ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
85bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
8649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView,
8749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            boolean overflowOnly, int popupStyleAttr) {
88ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mContext = context;
89ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mInflater = LayoutInflater.from(context);
90ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mMenu = menu;
9149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mAdapter = new MenuAdapter(mMenu);
92ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mOverflowOnly = overflowOnly;
9349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mPopupStyleAttr = popupStyleAttr;
94bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
95ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Resources res = context.getResources();
96ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2,
9707a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes                res.getDimensionPixelSize(R.dimen.abc_config_prefDialogWidth));
98bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
99ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mAnchorView = anchorView;
100bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
10149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // Present the menu using our context, not the menu builder's context.
10249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        menu.addMenuPresenter(this, context);
103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
104bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setAnchorView(View anchor) {
106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mAnchorView = anchor;
107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
108bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setForceShowIcon(boolean forceShow) {
110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mForceShowIcon = forceShow;
111bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
11349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void setGravity(int gravity) {
11449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mDropDownGravity = gravity;
11549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
11649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void show() {
118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!tryShow()) {
119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
121bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
122bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
12349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public ListPopupWindow getPopup() {
12449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return mPopup;
12549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
12649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
127ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean tryShow() {
12849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr);
129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setOnDismissListener(this);
130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setOnItemClickListener(this);
131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setAdapter(mAdapter);
132ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setModal(true);
133ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        View anchor = mAnchorView;
135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (anchor != null) {
136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final boolean addGlobalListener = mTreeObserver == null;
137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest
13849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this);
139ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPopup.setAnchorView(anchor);
14049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            mPopup.setDropDownGravity(mDropDownGravity);
141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return false;
143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
144bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
14549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (!mHasContentWidth) {
14649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            mContentWidth = measureContentWidth();
14749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            mHasContentWidth = true;
14849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
14949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
15049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mPopup.setContentWidth(mContentWidth);
151ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.show();
153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup.getListView().setOnKeyListener(this);
154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return true;
155bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void dismiss() {
158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (isShowing()) {
159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPopup.dismiss();
160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
161bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onDismiss() {
164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPopup = null;
165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mMenu.close();
166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mTreeObserver != null) {
16749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver();
168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mTreeObserver.removeGlobalOnLayoutListener(this);
169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mTreeObserver = null;
170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
171bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean isShowing() {
174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mPopup != null && mPopup.isShowing();
175bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
176bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        MenuAdapter adapter = mAdapter;
180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0);
181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
182bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean onKey(View v, int keyCode, KeyEvent event) {
184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) {
185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            dismiss();
186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return true;
187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
189bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
19149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private int measureContentWidth() {
192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Menus don't tend to be long, so this is more sane than it looks.
19349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        int maxWidth = 0;
194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        View itemView = null;
195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        int itemType = 0;
19649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
19749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final ListAdapter adapter = mAdapter;
19849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
19949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int count = adapter.getCount();
201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        for (int i = 0; i < count; i++) {
202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int positionType = adapter.getItemViewType(i);
203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (positionType != itemType) {
204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemType = positionType;
205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                itemView = null;
206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
20749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mMeasureParent == null) {
209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mMeasureParent = new FrameLayout(mContext);
210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
21149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            itemView = adapter.getView(i, itemView, mMeasureParent);
213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            itemView.measure(widthMeasureSpec, heightMeasureSpec);
21449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
21549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final int itemWidth = itemView.getMeasuredWidth();
21649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (itemWidth >= mPopupMaxWidth) {
21749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                return mPopupMaxWidth;
21849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            } else if (itemWidth > maxWidth) {
21949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                maxWidth = itemWidth;
22049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
221bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
22249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
22349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return maxWidth;
224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
225bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onGlobalLayout() {
228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (isShowing()) {
229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final View anchor = mAnchorView;
230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (anchor == null || !anchor.isShown()) {
231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                dismiss();
232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            } else if (isShowing()) {
233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                // Recompute window size and position
234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mPopup.show();
235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
236bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
237bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
238bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void initForMenu(Context context, MenuBuilder menu) {
241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Don't need to do anything; we added as a presenter in the constructor.
242bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
243bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuView getMenuView(ViewGroup root) {
246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        throw new UnsupportedOperationException("MenuPopupHelpers manage their own views");
247bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
248bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void updateMenuView(boolean cleared) {
25149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mHasContentWidth = false;
25249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
25320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (mAdapter != null) {
25420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            mAdapter.notifyDataSetChanged();
25520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
256bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
257bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCallback(Callback cb) {
260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mPresenterCallback = cb;
261bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
262bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (subMenu.hasVisibleItems()) {
26649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView);
267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            subPopup.setCallback(mPresenterCallback);
268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            boolean preserveIconSpacing = false;
270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int count = subMenu.size();
271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            for (int i = 0; i < count; i++) {
272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                MenuItem childItem = subMenu.getItem(i);
273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (childItem.isVisible() && childItem.getIcon() != null) {
274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    preserveIconSpacing = true;
275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    break;
276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            subPopup.setForceShowIcon(preserveIconSpacing);
279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (subPopup.tryShow()) {
281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                if (mPresenterCallback != null) {
282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    mPresenterCallback.onOpenSubMenu(subMenu);
283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return true;
285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
288bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
289bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Only care about the (sub)menu we're presenting.
29349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (menu != mMenu) return;
294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        dismiss();
296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mPresenterCallback != null) {
297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mPresenterCallback.onCloseMenu(menu, allMenusAreClosing);
298bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell        }
299bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
300bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
301bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    @Override
302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean flagActionItems() {
303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return false;
312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public int getId() {
316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return 0;
317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public Parcelable onSaveInstanceState() {
321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return null;
322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onRestoreInstanceState(Parcelable state) {
326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private class MenuAdapter extends BaseAdapter {
329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        private MenuBuilder mAdapterMenu;
330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        private int mExpandedIndex = -1;
331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public MenuAdapter(MenuBuilder menu) {
333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mAdapterMenu = menu;
334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            findExpandedIndex();
335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public int getCount() {
338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            ArrayList<MenuItemImpl> items = mOverflowOnly ?
33920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mExpandedIndex < 0) {
341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                return items.size();
342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.size() - 1;
344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public MenuItemImpl getItem(int position) {
347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            ArrayList<MenuItemImpl> items = mOverflowOnly ?
34820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems();
349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                position++;
351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return items.get(position);
353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public long getItemId(int position) {
356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Since a menu item's ID is optional, we'll use the position as an
357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // ID for the item in the AdapterView
358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return position;
359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public View getView(int position, View convertView, ViewGroup parent) {
362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (convertView == null) {
363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                convertView = mInflater.inflate(ITEM_LAYOUT, parent, false);
364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
365ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            MenuView.ItemView itemView = (MenuView.ItemView) convertView;
367ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mForceShowIcon) {
368ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                ((ListMenuItemView) convertView).setForceShowIcon(true);
369ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
370ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            itemView.initialize(getItem(position), 0);
371ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return convertView;
372ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
373ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
374ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        void findExpandedIndex() {
375ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final MenuItemImpl expandedItem = mMenu.getExpandedItem();
376ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (expandedItem != null) {
377ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
378ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                final int count = items.size();
379ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                for (int i = 0; i < count; i++) {
380ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    final MenuItemImpl item = items.get(i);
381ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    if (item == expandedItem) {
382ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        mExpandedIndex = i;
383ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                        return;
384ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                    }
385ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                }
386ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
387ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedIndex = -1;
388ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
389ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
390ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        @Override
391ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        public void notifyDataSetChanged() {
392ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            findExpandedIndex();
393ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            super.notifyDataSetChanged();
394ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
395bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell    }
396bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell}
397ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
398