ActionMenuItemView.java revision 7bc3ca0dc52be52ecad1c0de8c62a6a4bf8141ca
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.view.menu;
18
19import android.content.Context;
20import android.content.res.Resources;
21import android.graphics.Rect;
22import android.graphics.drawable.Drawable;
23import android.text.TextUtils;
24import android.util.AttributeSet;
25import android.view.Gravity;
26import android.view.MotionEvent;
27import android.view.View;
28import android.view.accessibility.AccessibilityEvent;
29import android.widget.Button;
30import android.widget.ImageButton;
31import android.widget.LinearLayout;
32import android.widget.Toast;
33
34/**
35 * @hide
36 */
37public class ActionMenuItemView extends LinearLayout
38        implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener,
39        ActionMenuView.ActionMenuChildView {
40    private static final String TAG = "ActionMenuItemView";
41
42    private MenuItemImpl mItemData;
43    private CharSequence mTitle;
44    private MenuBuilder.ItemInvoker mItemInvoker;
45
46    private ImageButton mImageButton;
47    private Button mTextButton;
48    private boolean mAllowTextWithIcon;
49    private boolean mShowTextAllCaps;
50    private boolean mExpandedFormat;
51
52    public ActionMenuItemView(Context context) {
53        this(context, null);
54    }
55
56    public ActionMenuItemView(Context context, AttributeSet attrs) {
57        this(context, attrs, 0);
58    }
59
60    public ActionMenuItemView(Context context, AttributeSet attrs, int defStyle) {
61        super(context, attrs, defStyle);
62        final Resources res = context.getResources();
63        mAllowTextWithIcon = res.getBoolean(
64                com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
65        mShowTextAllCaps = res.getBoolean(com.android.internal.R.bool.config_actionMenuItemAllCaps);
66    }
67
68    @Override
69    public void onFinishInflate() {
70        mImageButton = (ImageButton) findViewById(com.android.internal.R.id.imageButton);
71        mTextButton = (Button) findViewById(com.android.internal.R.id.textButton);
72        mImageButton.setOnClickListener(this);
73        mTextButton.setOnClickListener(this);
74        mImageButton.setOnLongClickListener(this);
75        setOnClickListener(this);
76        setOnLongClickListener(this);
77    }
78
79    public MenuItemImpl getItemData() {
80        return mItemData;
81    }
82
83    public void initialize(MenuItemImpl itemData, int menuType) {
84        mItemData = itemData;
85
86        setIcon(itemData.getIcon());
87        setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon
88        setId(itemData.getItemId());
89
90        setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
91        setEnabled(itemData.isEnabled());
92    }
93
94    @Override
95    public void setEnabled(boolean enabled) {
96        super.setEnabled(enabled);
97        mImageButton.setEnabled(enabled);
98        mTextButton.setEnabled(enabled);
99    }
100
101    public void onClick(View v) {
102        if (mItemInvoker != null) {
103            mItemInvoker.invokeItem(mItemData);
104        }
105    }
106
107    public void setItemInvoker(MenuBuilder.ItemInvoker invoker) {
108        mItemInvoker = invoker;
109    }
110
111    public boolean prefersCondensedTitle() {
112        return true;
113    }
114
115    public void setCheckable(boolean checkable) {
116        // TODO Support checkable action items
117    }
118
119    public void setChecked(boolean checked) {
120        // TODO Support checkable action items
121    }
122
123    public void setExpandedFormat(boolean expandedFormat) {
124        if (mExpandedFormat != expandedFormat) {
125            mExpandedFormat = expandedFormat;
126            if (mItemData != null) {
127                mItemData.actionFormatChanged();
128            }
129        }
130    }
131
132    private void updateTextButtonVisibility() {
133        boolean visible = !TextUtils.isEmpty(mTextButton.getText());
134        visible &= mImageButton.getDrawable() == null ||
135                (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat));
136
137        mTextButton.setVisibility(visible ? VISIBLE : GONE);
138    }
139
140    public void setIcon(Drawable icon) {
141        mImageButton.setImageDrawable(icon);
142        if (icon != null) {
143            mImageButton.setVisibility(VISIBLE);
144        } else {
145            mImageButton.setVisibility(GONE);
146        }
147
148        updateTextButtonVisibility();
149    }
150
151    public boolean hasText() {
152        return mTextButton.getVisibility() != GONE;
153    }
154
155    public void setShortcut(boolean showShortcut, char shortcutKey) {
156        // Action buttons don't show text for shortcut keys.
157    }
158
159    public void setTitle(CharSequence title) {
160        mTitle = title;
161
162        mTextButton.setText(mTitle);
163
164        setContentDescription(mTitle);
165        updateTextButtonVisibility();
166    }
167
168    @Override
169    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
170        onPopulateAccessibilityEvent(event);
171        return true;
172    }
173
174    @Override
175    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
176        super.onPopulateAccessibilityEvent(event);
177        final CharSequence cdesc = getContentDescription();
178        if (!TextUtils.isEmpty(cdesc)) {
179            event.getText().add(cdesc);
180        }
181    }
182
183    @Override
184    public boolean dispatchHoverEvent(MotionEvent event) {
185        // Don't allow children to hover; we want this to be treated as a single component.
186        return onHoverEvent(event);
187    }
188
189    public boolean showsIcon() {
190        return true;
191    }
192
193    public boolean needsDividerBefore() {
194        return hasText() && mItemData.getIcon() == null;
195    }
196
197    public boolean needsDividerAfter() {
198        return hasText();
199    }
200
201    @Override
202    public boolean onLongClick(View v) {
203        if (hasText()) {
204            // Don't show the cheat sheet for items that already show text.
205            return false;
206        }
207
208        final int[] screenPos = new int[2];
209        final Rect displayFrame = new Rect();
210        getLocationOnScreen(screenPos);
211        getWindowVisibleDisplayFrame(displayFrame);
212
213        final Context context = getContext();
214        final int width = getWidth();
215        final int height = getHeight();
216        final int midy = screenPos[1] + height / 2;
217        final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
218
219        Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
220        if (midy < displayFrame.height()) {
221            // Show along the top; follow action buttons
222            cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
223                    screenWidth - screenPos[0] - width / 2, height);
224        } else {
225            // Show along the bottom center
226            cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
227        }
228        cheatSheet.show();
229        return true;
230    }
231}
232