ActionMenuItemView.java revision 49c78900da0d43140fb602431fb93212bd7f6c70
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;
2049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.content.res.Configuration;
21bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.Resources;
22bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.TypedArray;
23bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.graphics.Rect;
24bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.graphics.drawable.Drawable;
2549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.os.Build;
2649c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.GravityCompat;
27da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
2889208232f3b5d1451408d787872504a190bc7ee0Chris Banesimport android.support.v7.internal.widget.CompatTextView;
2949c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.ActionMenuView;
3049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.ListPopupWindow;
31bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.text.TextUtils;
3230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.text.method.TransformationMethod;
33bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.util.AttributeSet;
34bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.Gravity;
3549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.MotionEvent;
36bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View;
37bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.Toast;
38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell
3930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport java.util.Locale;
4030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
41bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/**
42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * @hide
43bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */
4489208232f3b5d1451408d787872504a190bc7ee0Chris Banespublic class ActionMenuItemView extends CompatTextView
4520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener,
4620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        ActionMenuView.ActionMenuChildView {
4720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
48ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private static final String TAG = "ActionMenuItemView";
49ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
50ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuItemImpl mItemData;
51ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private CharSequence mTitle;
52ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private Drawable mIcon;
53ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private MenuBuilder.ItemInvoker mItemInvoker;
5449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private ListPopupWindow.ForwardingListener mForwardingListener;
5549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private PopupCallback mPopupCallback;
56ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
57ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mAllowTextWithIcon;
58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private boolean mExpandedFormat;
59ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private int mMinWidth;
60ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private int mSavedPaddingLeft;
61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
6249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private static final int MAX_ICON_SIZE = 32; // dp
6349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private int mMaxIconSize;
6449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public ActionMenuItemView(Context context) {
66ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        this(context, null);
67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
68ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public ActionMenuItemView(Context context, AttributeSet attrs) {
70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        this(context, attrs, 0);
71ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
72ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
73ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public ActionMenuItemView(Context context, AttributeSet attrs, int defStyle) {
74ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        super(context, attrs, defStyle);
75ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Resources res = context.getResources();
76ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mAllowTextWithIcon = res.getBoolean(
7749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                R.bool.abc_config_allowActionMenuItemTextWithIcon);
78ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        TypedArray a = context.obtainStyledAttributes(attrs,
7949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                R.styleable.ActionMenuItemView, defStyle, 0);
80ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mMinWidth = a.getDimensionPixelSize(
8120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                R.styleable.ActionMenuItemView_android_minWidth, 0);
82ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        a.recycle();
83ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
8449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final float density = res.getDisplayMetrics().density;
8549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mMaxIconSize = (int) (MAX_ICON_SIZE * density + 0.5f);
8649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
87ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setOnClickListener(this);
88ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setOnLongClickListener(this);
89ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        setTransformationMethod(new AllCapsTransformationMethod());
9130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
92ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mSavedPaddingLeft = -1;
93ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
94ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
9549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void onConfigurationChanged(Configuration newConfig) {
9649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (Build.VERSION.SDK_INT >= 8) {
9749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            super.onConfigurationChanged(newConfig);
9849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
9949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
10049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mAllowTextWithIcon = getContext().getResources().getBoolean(
10149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                R.bool.abc_config_allowActionMenuItemTextWithIcon);
10249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        updateTextButtonVisibility();
10349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
10449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
105ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setPadding(int l, int t, int r, int b) {
107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mSavedPaddingLeft = l;
108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        super.setPadding(l, t, r, b);
109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public MenuItemImpl getItemData() {
112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return mItemData;
113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void initialize(MenuItemImpl itemData, int menuType) {
116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mItemData = itemData;
117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setIcon(itemData.getIcon());
119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon
120ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setId(itemData.getItemId());
121ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
122ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setEnabled(itemData.isEnabled());
12449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (itemData.hasSubMenu()) {
12549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (mForwardingListener == null) {
12649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                mForwardingListener = new ActionMenuItemForwardingListener();
12749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
12849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
13149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    @Override
13249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public boolean onTouchEvent(MotionEvent e) {
13349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (mItemData.hasSubMenu() && mForwardingListener != null
13449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                && mForwardingListener.onTouch(this, e)) {
13549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            return true;
13649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
13749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return super.onTouchEvent(e);
13849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
13949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
14049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    @Override
141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void onClick(View v) {
142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mItemInvoker != null) {
143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mItemInvoker.invokeItem(mItemData);
144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setItemInvoker(MenuBuilder.ItemInvoker invoker) {
14820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        mItemInvoker = invoker;
149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
15149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void setPopupCallback(PopupCallback popupCallback) {
15249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mPopupCallback = popupCallback;
15349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
15449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
155ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean prefersCondensedTitle() {
156ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return true;
157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setCheckable(boolean checkable) {
160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // TODO Support checkable action items
161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setChecked(boolean checked) {
164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // TODO Support checkable action items
165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setExpandedFormat(boolean expandedFormat) {
168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (mExpandedFormat != expandedFormat) {
169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            mExpandedFormat = expandedFormat;
170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            if (mItemData != null) {
171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani                mItemData.actionFormatChanged();
172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            }
173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    private void updateTextButtonVisibility() {
177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        boolean visible = !TextUtils.isEmpty(mTitle);
178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        visible &= mIcon == null ||
17920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat));
180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setText(visible ? mTitle : null);
182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setIcon(Drawable icon) {
185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mIcon = icon;
18649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (icon != null) {
18749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            int width = icon.getIntrinsicWidth();
18849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            int height = icon.getIntrinsicHeight();
18949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (width > mMaxIconSize) {
19049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                final float scale = (float) mMaxIconSize / width;
19149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                width = mMaxIconSize;
19249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                height *= scale;
19349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
19449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (height > mMaxIconSize) {
19549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                final float scale = (float) mMaxIconSize / height;
19649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                height = mMaxIconSize;
19749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                width *= scale;
19849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
19949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            icon.setBounds(0, 0, width, height);
20049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
20149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        setCompoundDrawables(icon, null, null, null);
202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        updateTextButtonVisibility();
204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean hasText() {
207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return !TextUtils.isEmpty(getText());
208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setShortcut(boolean showShortcut, char shortcutKey) {
211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        // Action buttons don't show text for shortcut keys.
212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public void setTitle(CharSequence title) {
215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        mTitle = title;
216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        setContentDescription(mTitle);
218ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        updateTextButtonVisibility();
219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean showsIcon() {
222ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return true;
223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
225ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean needsDividerBefore() {
226ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return hasText() && mItemData.getIcon() == null;
227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean needsDividerAfter() {
230ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return hasText();
231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    public boolean onLongClick(View v) {
235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (hasText()) {
236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Don't show the cheat sheet for items that already show text.
237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            return false;
238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int[] screenPos = new int[2];
241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Rect displayFrame = new Rect();
242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        getLocationOnScreen(screenPos);
243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        getWindowVisibleDisplayFrame(displayFrame);
244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final Context context = getContext();
246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int width = getWidth();
247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int height = getHeight();
248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int midy = screenPos[1] + height / 2;
249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (midy < displayFrame.height()) {
253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Show along the top; follow action buttons
25449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            cheatSheet.setGravity(Gravity.TOP | GravityCompat.END,
25520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    screenWidth - screenPos[0] - width / 2, height);
256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        } else {
257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Show along the bottom center
258ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        cheatSheet.show();
261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        return true;
262ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
263ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
264ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    @Override
265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final boolean textVisible = hasText();
267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (textVisible && mSavedPaddingLeft >= 0) {
268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            super.setPadding(mSavedPaddingLeft, getPaddingTop(),
26920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    getPaddingRight(), getPaddingBottom());
270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int oldMeasuredWidth = getMeasuredWidth();
277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(widthSize, mMinWidth)
27820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                : mMinWidth;
279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (widthMode != MeasureSpec.EXACTLY && mMinWidth > 0 && oldMeasuredWidth < targetWidth) {
281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // Remeasure at exactly the minimum width.
282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            super.onMeasure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY),
28320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    heightMeasureSpec);
284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani
286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        if (!textVisible && mIcon != null) {
287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // TextView won't center compound drawables in both dimensions without
288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            // a little coercion. Pad in to center the icon after we've measured.
289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            final int w = getMeasuredWidth();
29049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final int dw = mIcon.getBounds().width();
291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani            super.setPadding((w - dw) / 2, getPaddingTop(), getPaddingRight(), getPaddingBottom());
292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani        }
293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani    }
29430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
29549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private class ActionMenuItemForwardingListener extends ListPopupWindow.ForwardingListener {
29649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public ActionMenuItemForwardingListener() {
29749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            super(ActionMenuItemView.this);
29849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
29949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
30049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
30149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public ListPopupWindow getPopup() {
30249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (mPopupCallback != null) {
30349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                return mPopupCallback.getPopup();
30449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
30549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            return null;
30649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
30749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
30849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
30949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        protected boolean onForwardingStarted() {
31049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            // Call the invoker, then check if the expected popup is showing.
31149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (mItemInvoker != null && mItemInvoker.invokeItem(mItemData)) {
31249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                final ListPopupWindow popup = getPopup();
31349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                return popup != null && popup.isShowing();
31449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
31549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            return false;
31649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
31749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
31849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
31949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        protected boolean onForwardingStopped() {
32049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final ListPopupWindow popup = getPopup();
32149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (popup != null) {
32249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                popup.dismiss();
32349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                return true;
32449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
32549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            return false;
32649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
32749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
32849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
32930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    private class AllCapsTransformationMethod implements TransformationMethod {
33030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        private Locale mLocale;
33130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
33230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public AllCapsTransformationMethod() {
33330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            mLocale = getContext().getResources().getConfiguration().locale;
33430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
33530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
33630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
33730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public CharSequence getTransformation(CharSequence source, View view) {
33830837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell            return source != null ? source.toString().toUpperCase(mLocale) : null;
33930837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
34030837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell
34130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        @Override
34230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        public void onFocusChanged(View view, CharSequence sourceText, boolean focused,
34330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell                int direction, Rect previouslyFocusedRect) {
34430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell        }
34530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    }
34649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
34749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public static abstract class PopupCallback {
34849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public abstract ListPopupWindow getPopup();
34949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
350bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell}
351