dcb50f3621261bdbf9ce3923e003f7edb891d561
[pub/Android/ownCloud.git] / actionbarsherlock / src / com / actionbarsherlock / internal / view / menu / ActionMenuItemView.java
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
17 package com.actionbarsherlock.internal.view.menu;
18
19 import java.util.HashSet;
20 import java.util.Set;
21 import android.content.Context;
22 import android.content.res.TypedArray;
23 import android.graphics.Rect;
24 import android.graphics.drawable.Drawable;
25 import android.os.Build;
26 import android.text.TextUtils;
27 import android.util.AttributeSet;
28 import android.view.Gravity;
29 import android.view.MotionEvent;
30 import android.view.View;
31 import android.view.accessibility.AccessibilityEvent;
32 import android.widget.ImageButton;
33 import android.widget.LinearLayout;
34 import android.widget.Toast;
35
36 import com.actionbarsherlock.R;
37 import com.actionbarsherlock.internal.view.View_HasStateListenerSupport;
38 import com.actionbarsherlock.internal.view.View_OnAttachStateChangeListener;
39 import com.actionbarsherlock.internal.widget.CapitalizingButton;
40
41 import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean;
42
43 /**
44 * @hide
45 */
46 public class ActionMenuItemView extends LinearLayout
47 implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener,
48 ActionMenuView.ActionMenuChildView, View_HasStateListenerSupport {
49 //UNUSED private static final String TAG = "ActionMenuItemView";
50
51 private MenuItemImpl mItemData;
52 private CharSequence mTitle;
53 private MenuBuilder.ItemInvoker mItemInvoker;
54
55 private ImageButton mImageButton;
56 private CapitalizingButton mTextButton;
57 private boolean mAllowTextWithIcon;
58 private boolean mExpandedFormat;
59 private int mMinWidth;
60
61 private final Set<View_OnAttachStateChangeListener> mListeners = new HashSet<View_OnAttachStateChangeListener>();
62
63 public ActionMenuItemView(Context context) {
64 this(context, null);
65 }
66
67 public ActionMenuItemView(Context context, AttributeSet attrs) {
68 this(context, attrs, 0);
69 }
70
71 public ActionMenuItemView(Context context, AttributeSet attrs, int defStyle) {
72 //TODO super(context, attrs, defStyle);
73 super(context, attrs);
74 mAllowTextWithIcon = getResources_getBoolean(context,
75 R.bool.abs__config_allowActionMenuItemTextWithIcon);
76 TypedArray a = context.obtainStyledAttributes(attrs,
77 R.styleable.SherlockActionMenuItemView, 0, 0);
78 mMinWidth = a.getDimensionPixelSize(
79 R.styleable.SherlockActionMenuItemView_android_minWidth, 0);
80 a.recycle();
81 }
82
83 @Override
84 public void addOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) {
85 mListeners.add(listener);
86 }
87
88 @Override
89 public void removeOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) {
90 mListeners.remove(listener);
91 }
92
93 @Override
94 protected void onAttachedToWindow() {
95 super.onAttachedToWindow();
96 for (View_OnAttachStateChangeListener listener : mListeners) {
97 listener.onViewAttachedToWindow(this);
98 }
99 }
100
101 @Override
102 protected void onDetachedFromWindow() {
103 super.onDetachedFromWindow();
104 for (View_OnAttachStateChangeListener listener : mListeners) {
105 listener.onViewDetachedFromWindow(this);
106 }
107 }
108
109 @Override
110 public void onFinishInflate() {
111
112 mImageButton = (ImageButton) findViewById(R.id.abs__imageButton);
113 mTextButton = (CapitalizingButton) findViewById(R.id.abs__textButton);
114 mImageButton.setOnClickListener(this);
115 mTextButton.setOnClickListener(this);
116 mImageButton.setOnLongClickListener(this);
117 setOnClickListener(this);
118 setOnLongClickListener(this);
119 }
120
121 public MenuItemImpl getItemData() {
122 return mItemData;
123 }
124
125 public void initialize(MenuItemImpl itemData, int menuType) {
126 mItemData = itemData;
127
128 setIcon(itemData.getIcon());
129 setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon
130 setId(itemData.getItemId());
131
132 setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
133 setEnabled(itemData.isEnabled());
134 }
135
136 @Override
137 public void setEnabled(boolean enabled) {
138 super.setEnabled(enabled);
139 mImageButton.setEnabled(enabled);
140 mTextButton.setEnabled(enabled);
141 }
142
143 public void onClick(View v) {
144 if (mItemInvoker != null) {
145 mItemInvoker.invokeItem(mItemData);
146 }
147 }
148
149 public void setItemInvoker(MenuBuilder.ItemInvoker invoker) {
150 mItemInvoker = invoker;
151 }
152
153 public boolean prefersCondensedTitle() {
154 return true;
155 }
156
157 public void setCheckable(boolean checkable) {
158 // TODO Support checkable action items
159 }
160
161 public void setChecked(boolean checked) {
162 // TODO Support checkable action items
163 }
164
165 public void setExpandedFormat(boolean expandedFormat) {
166 if (mExpandedFormat != expandedFormat) {
167 mExpandedFormat = expandedFormat;
168 if (mItemData != null) {
169 mItemData.actionFormatChanged();
170 }
171 }
172 }
173
174 private void updateTextButtonVisibility() {
175 boolean visible = !TextUtils.isEmpty(mTextButton.getText());
176 visible &= mImageButton.getDrawable() == null ||
177 (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat));
178
179 mTextButton.setVisibility(visible ? VISIBLE : GONE);
180 }
181
182 public void setIcon(Drawable icon) {
183 mImageButton.setImageDrawable(icon);
184 if (icon != null) {
185 mImageButton.setVisibility(VISIBLE);
186 } else {
187 mImageButton.setVisibility(GONE);
188 }
189
190 updateTextButtonVisibility();
191 }
192
193 public boolean hasText() {
194 return mTextButton.getVisibility() != GONE;
195 }
196
197 public void setShortcut(boolean showShortcut, char shortcutKey) {
198 // Action buttons don't show text for shortcut keys.
199 }
200
201 public void setTitle(CharSequence title) {
202 mTitle = title;
203
204 mTextButton.setTextCompat(mTitle);
205
206 setContentDescription(mTitle);
207 updateTextButtonVisibility();
208 }
209
210 @Override
211 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
212 onPopulateAccessibilityEvent(event);
213 return true;
214 }
215
216 @Override
217 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
218 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
219 super.onPopulateAccessibilityEvent(event);
220 }
221 final CharSequence cdesc = getContentDescription();
222 if (!TextUtils.isEmpty(cdesc)) {
223 event.getText().add(cdesc);
224 }
225 }
226
227 @Override
228 public boolean dispatchHoverEvent(MotionEvent event) {
229 // Don't allow children to hover; we want this to be treated as a single component.
230 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
231 return onHoverEvent(event);
232 }
233 return false;
234 }
235
236 public boolean showsIcon() {
237 return true;
238 }
239
240 public boolean needsDividerBefore() {
241 return hasText() && mItemData.getIcon() == null;
242 }
243
244 public boolean needsDividerAfter() {
245 return hasText();
246 }
247
248 @Override
249 public boolean onLongClick(View v) {
250 if (hasText()) {
251 // Don't show the cheat sheet for items that already show text.
252 return false;
253 }
254
255 final int[] screenPos = new int[2];
256 final Rect displayFrame = new Rect();
257 getLocationOnScreen(screenPos);
258 getWindowVisibleDisplayFrame(displayFrame);
259
260 final Context context = getContext();
261 final int width = getWidth();
262 final int height = getHeight();
263 final int midy = screenPos[1] + height / 2;
264 final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
265
266 Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
267 if (midy < displayFrame.height()) {
268 // Show along the top; follow action buttons
269 cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
270 screenWidth - screenPos[0] - width / 2, height);
271 } else {
272 // Show along the bottom center
273 cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
274 }
275 cheatSheet.show();
276 return true;
277 }
278
279 @Override
280 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
281 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
282
283 final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
284 final int specSize = MeasureSpec.getSize(widthMeasureSpec);
285 final int oldMeasuredWidth = getMeasuredWidth();
286 final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(specSize, mMinWidth)
287 : mMinWidth;
288
289 if (widthMode != MeasureSpec.EXACTLY && mMinWidth > 0 && oldMeasuredWidth < targetWidth) {
290 // Remeasure at exactly the minimum width.
291 super.onMeasure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY),
292 heightMeasureSpec);
293 }
294 }
295 }