blob: 15e271edc882cc12332c3fb48616341ff106bda5 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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
Adam Powell696cba52011-03-29 10:38:16 -070019import com.android.internal.view.menu.MenuView.ItemView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -040021import android.annotation.Nullable;
Adam Powell151af192010-05-04 14:44:45 -070022import android.content.ActivityNotFoundException;
Adam Powell81cf3ec2011-05-17 10:20:33 -070023import android.content.Context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.Intent;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -040025import android.content.res.ColorStateList;
26import android.graphics.PorterDuff;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.graphics.drawable.Drawable;
Adam Powell151af192010-05-04 14:44:45 -070028import android.util.Log;
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -070029import android.view.ActionProvider;
Adam Powell696cba52011-03-29 10:38:16 -070030import android.view.ContextMenu.ContextMenuInfo;
Peeyush Agarwale631e322016-10-19 11:41:42 +010031import android.view.KeyEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.view.LayoutInflater;
33import android.view.MenuItem;
34import android.view.SubMenu;
35import android.view.View;
36import android.view.ViewDebug;
Adam Powell81cf3ec2011-05-17 10:20:33 -070037import android.widget.LinearLayout;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
39/**
40 * @hide
41 */
42public final class MenuItemImpl implements MenuItem {
Adam Powell151af192010-05-04 14:44:45 -070043 private static final String TAG = "MenuItemImpl";
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -040044
Adam Powelld8404b22010-10-13 14:26:41 -070045 private static final int SHOW_AS_ACTION_MASK = SHOW_AS_ACTION_NEVER |
46 SHOW_AS_ACTION_IF_ROOM |
47 SHOW_AS_ACTION_ALWAYS;
48
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 private final int mId;
50 private final int mGroup;
51 private final int mCategoryOrder;
52 private final int mOrdering;
53 private CharSequence mTitle;
54 private CharSequence mTitleCondensed;
55 private Intent mIntent;
56 private char mShortcutNumericChar;
Peeyush Agarwale631e322016-10-19 11:41:42 +010057 private int mShortcutNumericModifiers = KeyEvent.META_CTRL_ON;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 private char mShortcutAlphabeticChar;
Peeyush Agarwale631e322016-10-19 11:41:42 +010059 private int mShortcutAlphabeticModifiers = KeyEvent.META_CTRL_ON;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060
61 /** The icon's drawable which is only created as needed */
62 private Drawable mIconDrawable;
63 /**
64 * The icon's resource ID which is used to get the Drawable when it is
65 * needed (if the Drawable isn't already obtained--only one of the two is
66 * needed).
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -040067 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 private int mIconResId = NO_ICON;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -040069
70 private ColorStateList mIconTintList = null;
71 private PorterDuff.Mode mIconTintMode = null;
72 private boolean mHasIconTint = false;
73 private boolean mHasIconTintMode = false;
74 private boolean mNeedToApplyIconTint = false;
75
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 /** The menu to which this item belongs */
77 private MenuBuilder mMenu;
78 /** If this item should launch a sub menu, this is the sub menu to launch */
79 private SubMenuBuilder mSubMenu;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -040080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 private Runnable mItemCallback;
82 private MenuItem.OnMenuItemClickListener mClickListener;
83
84 private int mFlags = ENABLED;
85 private static final int CHECKABLE = 0x00000001;
86 private static final int CHECKED = 0x00000002;
87 private static final int EXCLUSIVE = 0x00000004;
88 private static final int HIDDEN = 0x00000008;
89 private static final int ENABLED = 0x00000010;
Adam Powell96675b12010-06-10 18:58:59 -070090 private static final int IS_ACTION = 0x00000020;
Adam Powell89e06452010-06-23 20:24:52 -070091
Adam Powell96675b12010-06-10 18:58:59 -070092 private int mShowAsAction = SHOW_AS_ACTION_NEVER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
Adam Powellcf78b3e2010-09-12 18:25:23 -070094 private View mActionView;
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -070095 private ActionProvider mActionProvider;
Adam Powell8d02dea2011-05-31 21:35:13 -070096 private OnActionExpandListener mOnActionExpandListener;
97 private boolean mIsActionViewExpanded = false;
Adam Powellcf78b3e2010-09-12 18:25:23 -070098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 /** Used for the icon resource ID if this item does not have an icon */
100 static final int NO_ICON = 0;
101
102 /**
103 * Current use case is for context menu: Extra information linked to the
104 * View that added this item to the context menu.
Vladislav Kaznacheev7039cbc2017-01-04 10:15:31 -0800105 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 private ContextMenuInfo mMenuInfo;
Vladislav Kaznacheev7039cbc2017-01-04 10:15:31 -0800107
108 private CharSequence mContentDescription;
Vladislav Kaznacheev6a944ca2017-01-19 11:02:12 -0800109 private CharSequence mTooltipText;
Vladislav Kaznacheev7039cbc2017-01-04 10:15:31 -0800110
Mattias Falkeb573412011-04-19 16:13:14 +0200111 private static String sLanguage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 private static String sPrependShortcutLabel;
113 private static String sEnterShortcutLabel;
114 private static String sDeleteShortcutLabel;
115 private static String sSpaceShortcutLabel;
Vladislav Kaznacheev7039cbc2017-01-04 10:15:31 -0800116
117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 /**
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700119 * Instantiates this menu item.
120 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 * @param menu
122 * @param group Item ordering grouping control. The item will be added after
123 * all other items whose order is <= this number, and before any
124 * that are larger than it. This can also be used to define
125 * groups of items for batch state changes. Normally use 0.
126 * @param id Unique item ID. Use 0 if you do not need a unique ID.
127 * @param categoryOrder The ordering for this item.
128 * @param title The text to display for the item.
129 */
130 MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
Adam Powell4d9861e2010-08-17 11:14:40 -0700131 CharSequence title, int showAsAction) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132
Mattias Falkeb573412011-04-19 16:13:14 +0200133 String lang = menu.getContext().getResources().getConfiguration().locale.toString();
134 if (sPrependShortcutLabel == null || !lang.equals(sLanguage)) {
135 sLanguage = lang;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400136 // This is instantiated from the UI thread, so no chance of sync issues
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 sPrependShortcutLabel = menu.getContext().getResources().getString(
138 com.android.internal.R.string.prepend_shortcut_label);
139 sEnterShortcutLabel = menu.getContext().getResources().getString(
140 com.android.internal.R.string.menu_enter_shortcut_label);
141 sDeleteShortcutLabel = menu.getContext().getResources().getString(
142 com.android.internal.R.string.menu_delete_shortcut_label);
143 sSpaceShortcutLabel = menu.getContext().getResources().getString(
144 com.android.internal.R.string.menu_space_shortcut_label);
145 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 mMenu = menu;
148 mId = id;
149 mGroup = group;
150 mCategoryOrder = categoryOrder;
151 mOrdering = ordering;
152 mTitle = title;
Adam Powell4d9861e2010-08-17 11:14:40 -0700153 mShowAsAction = showAsAction;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 /**
157 * Invokes the item by calling various listeners or callbacks.
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400158 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 * @return true if the invocation was handled, false otherwise
160 */
161 public boolean invoke() {
162 if (mClickListener != null &&
163 mClickListener.onMenuItemClick(this)) {
164 return true;
165 }
166
Alan Viverette53023ff2015-09-18 13:20:20 -0400167 if (mMenu.dispatchMenuItemSelected(mMenu, this)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 return true;
169 }
170
171 if (mItemCallback != null) {
172 mItemCallback.run();
173 return true;
174 }
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 if (mIntent != null) {
Adam Powell151af192010-05-04 14:44:45 -0700177 try {
178 mMenu.getContext().startActivity(mIntent);
179 return true;
180 } catch (ActivityNotFoundException e) {
181 Log.e(TAG, "Can't find activity to handle intent; ignoring", e);
182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 }
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700184
Adam Powell961dd112011-07-12 14:25:23 -0700185 if (mActionProvider != null && mActionProvider.onPerformDefaultAction()) {
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700186 return true;
187 }
188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 return false;
190 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 public boolean isEnabled() {
193 return (mFlags & ENABLED) != 0;
194 }
195
196 public MenuItem setEnabled(boolean enabled) {
197 if (enabled) {
198 mFlags |= ENABLED;
199 } else {
200 mFlags &= ~ENABLED;
201 }
202
Adam Powell696cba52011-03-29 10:38:16 -0700203 mMenu.onItemsChanged(false);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 return this;
206 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 public int getGroupId() {
209 return mGroup;
210 }
211
212 @ViewDebug.CapturedViewProperty
213 public int getItemId() {
214 return mId;
215 }
216
217 public int getOrder() {
218 return mCategoryOrder;
219 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 public int getOrdering() {
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400222 return mOrdering;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 public Intent getIntent() {
226 return mIntent;
227 }
228
229 public MenuItem setIntent(Intent intent) {
230 mIntent = intent;
231 return this;
232 }
233
234 Runnable getCallback() {
235 return mItemCallback;
236 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 public MenuItem setCallback(Runnable callback) {
239 mItemCallback = callback;
240 return this;
241 }
Peeyush Agarwale631e322016-10-19 11:41:42 +0100242
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100243 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 public char getAlphabeticShortcut() {
245 return mShortcutAlphabeticChar;
246 }
247
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100248 @Override
Peeyush Agarwale631e322016-10-19 11:41:42 +0100249 public int getAlphabeticModifiers() {
250 return mShortcutAlphabeticModifiers;
251 }
252
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100253 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 public MenuItem setAlphabeticShortcut(char alphaChar) {
255 if (mShortcutAlphabeticChar == alphaChar) return this;
Peeyush Agarwale631e322016-10-19 11:41:42 +0100256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
Peeyush Agarwale631e322016-10-19 11:41:42 +0100258
Adam Powell696cba52011-03-29 10:38:16 -0700259 mMenu.onItemsChanged(false);
Peeyush Agarwale631e322016-10-19 11:41:42 +0100260
261 return this;
262 }
263
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100264 @Override
Peeyush Agarwale631e322016-10-19 11:41:42 +0100265 public MenuItem setAlphabeticShortcut(char alphaChar, int alphaModifiers){
266 if (mShortcutAlphabeticChar == alphaChar &&
267 mShortcutAlphabeticModifiers == alphaModifiers) {
268 return this;
269 }
270
Peeyush Agarwal2ef1d0c2017-03-06 17:03:58 +0000271 mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
Peeyush Agarwale631e322016-10-19 11:41:42 +0100272 mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
273
274 mMenu.onItemsChanged(false);
275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 return this;
277 }
278
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100279 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 public char getNumericShortcut() {
281 return mShortcutNumericChar;
282 }
283
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100284 @Override
Peeyush Agarwale631e322016-10-19 11:41:42 +0100285 public int getNumericModifiers() {
286 return mShortcutNumericModifiers;
287 }
288
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100289 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 public MenuItem setNumericShortcut(char numericChar) {
291 if (mShortcutNumericChar == numericChar) return this;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 mShortcutNumericChar = numericChar;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400294
Adam Powell696cba52011-03-29 10:38:16 -0700295 mMenu.onItemsChanged(false);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 return this;
298 }
299
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100300 @Override
Peeyush Agarwale631e322016-10-19 11:41:42 +0100301 public MenuItem setNumericShortcut(char numericChar, int numericModifiers){
302 if (mShortcutNumericChar == numericChar && mShortcutNumericModifiers == numericModifiers) {
303 return this;
304 }
305
306 mShortcutNumericChar = numericChar;
307 mShortcutNumericModifiers = KeyEvent.normalizeMetaState(numericModifiers);
308
309 mMenu.onItemsChanged(false);
310
311 return this;
312 }
313
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100314 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 public MenuItem setShortcut(char numericChar, char alphaChar) {
316 mShortcutNumericChar = numericChar;
317 mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400318
Adam Powell696cba52011-03-29 10:38:16 -0700319 mMenu.onItemsChanged(false);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 return this;
322 }
323
Peeyush Agarwal101ab582017-05-11 14:19:22 +0100324 @Override
325 public MenuItem setShortcut(char numericChar, char alphaChar, int numericModifiers,
Peeyush Agarwale631e322016-10-19 11:41:42 +0100326 int alphaModifiers) {
327 mShortcutNumericChar = numericChar;
328 mShortcutNumericModifiers = KeyEvent.normalizeMetaState(numericModifiers);
Peeyush Agarwal2ef1d0c2017-03-06 17:03:58 +0000329 mShortcutAlphabeticChar = Character.toLowerCase(alphaChar);
Peeyush Agarwale631e322016-10-19 11:41:42 +0100330 mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers);
331
332 mMenu.onItemsChanged(false);
333
334 return this;
335 }
336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 /**
338 * @return The active shortcut (based on QWERTY-mode of the menu).
339 */
340 char getShortcut() {
341 return (mMenu.isQwertyMode() ? mShortcutAlphabeticChar : mShortcutNumericChar);
342 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 /**
345 * @return The label to show for the shortcut. This includes the chording
346 * key (for example 'Menu+a'). Also, any non-human readable
347 * characters should be human readable (for example 'Menu+enter').
348 */
349 String getShortcutLabel() {
350
351 char shortcut = getShortcut();
352 if (shortcut == 0) {
353 return "";
354 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 StringBuilder sb = new StringBuilder(sPrependShortcutLabel);
357 switch (shortcut) {
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 case '\n':
360 sb.append(sEnterShortcutLabel);
361 break;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 case '\b':
364 sb.append(sDeleteShortcutLabel);
365 break;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 case ' ':
368 sb.append(sSpaceShortcutLabel);
369 break;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 default:
372 sb.append(shortcut);
373 break;
374 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 return sb.toString();
377 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 /**
380 * @return Whether this menu item should be showing shortcuts (depends on
381 * whether the menu should show shortcuts and whether this item has
382 * a shortcut defined)
383 */
384 boolean shouldShowShortcut() {
385 // Show shortcuts if the menu is supposed to show shortcuts AND this item has a shortcut
386 return mMenu.isShortcutsVisible() && (getShortcut() != 0);
387 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 public SubMenu getSubMenu() {
390 return mSubMenu;
391 }
392
393 public boolean hasSubMenu() {
394 return mSubMenu != null;
395 }
396
397 void setSubMenu(SubMenuBuilder subMenu) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 mSubMenu = subMenu;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 subMenu.setHeaderTitle(getTitle());
401 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 @ViewDebug.CapturedViewProperty
404 public CharSequence getTitle() {
405 return mTitle;
406 }
407
408 /**
409 * Gets the title for a particular {@link ItemView}
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400410 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 * @param itemView The ItemView that is receiving the title
412 * @return Either the title or condensed title based on what the ItemView
413 * prefers
414 */
415 CharSequence getTitleForItemView(MenuView.ItemView itemView) {
416 return ((itemView != null) && itemView.prefersCondensedTitle())
417 ? getTitleCondensed()
418 : getTitle();
419 }
420
421 public MenuItem setTitle(CharSequence title) {
422 mTitle = title;
423
Adam Powell696cba52011-03-29 10:38:16 -0700424 mMenu.onItemsChanged(false);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 if (mSubMenu != null) {
427 mSubMenu.setHeaderTitle(title);
428 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 return this;
431 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 public MenuItem setTitle(int title) {
434 return setTitle(mMenu.getContext().getString(title));
435 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 public CharSequence getTitleCondensed() {
438 return mTitleCondensed != null ? mTitleCondensed : mTitle;
439 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 public MenuItem setTitleCondensed(CharSequence title) {
442 mTitleCondensed = title;
443
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400444 // Could use getTitle() in the loop below, but just cache what it would do here
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 if (title == null) {
446 title = mTitle;
447 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400448
Adam Powell696cba52011-03-29 10:38:16 -0700449 mMenu.onItemsChanged(false);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 return this;
452 }
453
454 public Drawable getIcon() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 if (mIconDrawable != null) {
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400456 return applyIconTintIfNecessary(mIconDrawable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458
459 if (mIconResId != NO_ICON) {
Chris Banesa41b7892015-06-09 13:36:44 +0000460 Drawable icon = mMenu.getContext().getDrawable(mIconResId);
Adam Powellc4852a32012-03-19 15:35:46 -0700461 mIconResId = NO_ICON;
Chris Banesa41b7892015-06-09 13:36:44 +0000462 mIconDrawable = icon;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400463 return applyIconTintIfNecessary(icon);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 return null;
467 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 public MenuItem setIcon(Drawable icon) {
470 mIconResId = NO_ICON;
471 mIconDrawable = icon;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400472 mNeedToApplyIconTint = true;
Adam Powell696cba52011-03-29 10:38:16 -0700473 mMenu.onItemsChanged(false);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 return this;
476 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 public MenuItem setIcon(int iconResId) {
479 mIconDrawable = null;
480 mIconResId = iconResId;
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400481 mNeedToApplyIconTint = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482
483 // If we have a view, we need to push the Drawable to them
Adam Powell696cba52011-03-29 10:38:16 -0700484 mMenu.onItemsChanged(false);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 return this;
487 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400488
489 @Override
490 public MenuItem setIconTintList(@Nullable ColorStateList iconTintList) {
491 mIconTintList = iconTintList;
492 mHasIconTint = true;
493 mNeedToApplyIconTint = true;
494
495 mMenu.onItemsChanged(false);
496
497 return this;
498 }
499
500 @Nullable
501 @Override
502 public ColorStateList getIconTintList() {
503 return mIconTintList;
504 }
505
506 @Override
507 public MenuItem setIconTintMode(PorterDuff.Mode iconTintMode) {
508 mIconTintMode = iconTintMode;
509 mHasIconTintMode = true;
510 mNeedToApplyIconTint = true;
511
512 mMenu.onItemsChanged(false);
513
514 return this;
515 }
516
517 @Nullable
518 @Override
519 public PorterDuff.Mode getIconTintMode() {
520 return mIconTintMode;
521 }
522
523 private Drawable applyIconTintIfNecessary(Drawable icon) {
524 if (icon != null && mNeedToApplyIconTint && (mHasIconTint || mHasIconTintMode)) {
525 icon = icon.mutate();
526
527 if (mHasIconTint) {
528 icon.setTintList(mIconTintList);
529 }
530
531 if (mHasIconTintMode) {
532 icon.setTintMode(mIconTintMode);
533 }
534
535 mNeedToApplyIconTint = false;
536 }
537
538 return icon;
539 }
540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 public boolean isCheckable() {
542 return (mFlags & CHECKABLE) == CHECKABLE;
543 }
544
545 public MenuItem setCheckable(boolean checkable) {
546 final int oldFlags = mFlags;
547 mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0);
548 if (oldFlags != mFlags) {
Adam Powell696cba52011-03-29 10:38:16 -0700549 mMenu.onItemsChanged(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 return this;
553 }
554
Adam Powell696cba52011-03-29 10:38:16 -0700555 public void setExclusiveCheckable(boolean exclusive) {
556 mFlags = (mFlags & ~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 }
558
559 public boolean isExclusiveCheckable() {
560 return (mFlags & EXCLUSIVE) != 0;
561 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 public boolean isChecked() {
564 return (mFlags & CHECKED) == CHECKED;
565 }
566
567 public MenuItem setChecked(boolean checked) {
568 if ((mFlags & EXCLUSIVE) != 0) {
569 // Call the method on the Menu since it knows about the others in this
570 // exclusive checkable group
571 mMenu.setExclusiveItemChecked(this);
572 } else {
573 setCheckedInt(checked);
574 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 return this;
577 }
578
579 void setCheckedInt(boolean checked) {
580 final int oldFlags = mFlags;
581 mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0);
582 if (oldFlags != mFlags) {
Adam Powell696cba52011-03-29 10:38:16 -0700583 mMenu.onItemsChanged(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 }
585 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 public boolean isVisible() {
Adam Powell130b4572012-06-15 19:21:34 -0700588 if (mActionProvider != null && mActionProvider.overridesItemVisibility()) {
589 return (mFlags & HIDDEN) == 0 && mActionProvider.isVisible();
590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 return (mFlags & HIDDEN) == 0;
592 }
593
594 /**
595 * Changes the visibility of the item. This method DOES NOT notify the
596 * parent menu of a change in this item, so this should only be called from
597 * methods that will eventually trigger this change. If unsure, use {@link #setVisible(boolean)}
598 * instead.
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400599 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 * @param shown Whether to show (true) or hide (false).
601 * @return Whether the item's shown state was changed
602 */
603 boolean setVisibleInt(boolean shown) {
604 final int oldFlags = mFlags;
605 mFlags = (mFlags & ~HIDDEN) | (shown ? 0 : HIDDEN);
606 return oldFlags != mFlags;
607 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 public MenuItem setVisible(boolean shown) {
610 // Try to set the shown state to the given state. If the shown state was changed
611 // (i.e. the previous state isn't the same as given state), notify the parent menu that
612 // the shown state has changed for this item
613 if (setVisibleInt(shown)) mMenu.onItemVisibleChanged(this);
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 return this;
616 }
617
618 public MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener clickListener) {
619 mClickListener = clickListener;
620 return this;
621 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 @Override
624 public String toString() {
Chet Haasecb923d92014-06-30 17:59:15 -0700625 return mTitle != null ? mTitle.toString() : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 }
627
628 void setMenuInfo(ContextMenuInfo menuInfo) {
629 mMenuInfo = menuInfo;
630 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 public ContextMenuInfo getMenuInfo() {
633 return mMenuInfo;
634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635
Adam Powell35aecd52011-07-01 13:43:49 -0700636 public void actionFormatChanged() {
637 mMenu.onItemActionRequestChanged(this);
638 }
639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 /**
Adam Powell696cba52011-03-29 10:38:16 -0700641 * @return Whether the menu should show icons for menu items.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800642 */
Adam Powell696cba52011-03-29 10:38:16 -0700643 public boolean shouldShowIcon() {
644 return mMenu.getOptionalIconsVisible();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400646
Adam Powell96675b12010-06-10 18:58:59 -0700647 public boolean isActionButton() {
Adam Powellea1ca952011-06-21 14:07:59 -0700648 return (mFlags & IS_ACTION) == IS_ACTION;
Adam Powell96675b12010-06-10 18:58:59 -0700649 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400650
Adam Powell96675b12010-06-10 18:58:59 -0700651 public boolean requestsActionButton() {
Adam Powelld8404b22010-10-13 14:26:41 -0700652 return (mShowAsAction & SHOW_AS_ACTION_IF_ROOM) == SHOW_AS_ACTION_IF_ROOM;
Adam Powell96675b12010-06-10 18:58:59 -0700653 }
Kirill Grouchnikov6eea0d22017-03-21 13:52:09 -0400654
Adam Powell96675b12010-06-10 18:58:59 -0700655 public boolean requiresActionButton() {
Adam Powelld8404b22010-10-13 14:26:41 -0700656 return (mShowAsAction & SHOW_AS_ACTION_ALWAYS) == SHOW_AS_ACTION_ALWAYS;
Adam Powell96675b12010-06-10 18:58:59 -0700657 }
658
Siyamed Sinir484c2e22017-06-07 16:26:19 -0700659 @Override
660 public boolean requiresOverflow() {
661 return (mShowAsAction & SHOW_AS_OVERFLOW_ALWAYS) == SHOW_AS_OVERFLOW_ALWAYS;
662 }
663
Adam Powell96675b12010-06-10 18:58:59 -0700664 public void setIsActionButton(boolean isActionButton) {
665 if (isActionButton) {
666 mFlags |= IS_ACTION;
667 } else {
668 mFlags &= ~IS_ACTION;
669 }
670 }
Adam Powell89e06452010-06-23 20:24:52 -0700671
Adam Powelld8404b22010-10-13 14:26:41 -0700672 public boolean showsTextAsAction() {
Adam Powell35aecd52011-07-01 13:43:49 -0700673 return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT;
Adam Powelld8404b22010-10-13 14:26:41 -0700674 }
675
Adam Powell96675b12010-06-10 18:58:59 -0700676 public void setShowAsAction(int actionEnum) {
Adam Powelld8404b22010-10-13 14:26:41 -0700677 switch (actionEnum & SHOW_AS_ACTION_MASK) {
678 case SHOW_AS_ACTION_ALWAYS:
679 case SHOW_AS_ACTION_IF_ROOM:
680 case SHOW_AS_ACTION_NEVER:
681 // Looks good!
682 break;
683
684 default:
685 // Mutually exclusive options selected!
686 throw new IllegalArgumentException("SHOW_AS_ACTION_ALWAYS, SHOW_AS_ACTION_IF_ROOM,"
687 + " and SHOW_AS_ACTION_NEVER are mutually exclusive.");
688 }
Adam Powell96675b12010-06-10 18:58:59 -0700689 mShowAsAction = actionEnum;
690 mMenu.onItemActionRequestChanged(this);
691 }
Adam Powellcf78b3e2010-09-12 18:25:23 -0700692
693 public MenuItem setActionView(View view) {
694 mActionView = view;
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700695 mActionProvider = null;
Adam Powell038f1c82011-07-21 14:28:10 -0700696 if (view != null && view.getId() == View.NO_ID && mId > 0) {
697 view.setId(mId);
698 }
Adam Powellabbcc242011-01-24 11:48:54 -0800699 mMenu.onItemActionRequestChanged(this);
Adam Powellcf78b3e2010-09-12 18:25:23 -0700700 return this;
701 }
702
Adam Powell3f476b32011-01-03 19:25:36 -0800703 public MenuItem setActionView(int resId) {
Adam Powell81cf3ec2011-05-17 10:20:33 -0700704 final Context context = mMenu.getContext();
705 final LayoutInflater inflater = LayoutInflater.from(context);
Amith Yamasani10da5902011-07-26 16:14:26 -0700706 setActionView(inflater.inflate(resId, new LinearLayout(context), false));
Adam Powell3f476b32011-01-03 19:25:36 -0800707 return this;
708 }
709
Adam Powellcf78b3e2010-09-12 18:25:23 -0700710 public View getActionView() {
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700711 if (mActionView != null) {
712 return mActionView;
713 } else if (mActionProvider != null) {
Adam Powell690ffb42012-06-04 19:22:45 -0700714 mActionView = mActionProvider.onCreateActionView(this);
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700715 return mActionView;
716 } else {
717 return null;
718 }
719 }
720
721 public ActionProvider getActionProvider() {
722 return mActionProvider;
723 }
724
725 public MenuItem setActionProvider(ActionProvider actionProvider) {
Adam Powell39d5c612012-06-16 14:25:38 -0700726 if (mActionProvider != null) {
Chris Banesc8f6ecc2015-06-30 11:16:37 +0100727 mActionProvider.reset();
Adam Powell39d5c612012-06-16 14:25:38 -0700728 }
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700729 mActionView = null;
730 mActionProvider = actionProvider;
Adam Powell23f4cc02011-08-18 10:30:46 -0700731 mMenu.onItemsChanged(true); // Measurement can be changed
Adam Powelldcc55852013-05-03 11:03:10 -0700732 if (mActionProvider != null) {
733 mActionProvider.setVisibilityListener(new ActionProvider.VisibilityListener() {
734 @Override public void onActionProviderVisibilityChanged(boolean isVisible) {
735 mMenu.onItemVisibleChanged(MenuItemImpl.this);
736 }
737 });
738 }
Svetoslav Ganov51ac0e92011-06-17 13:45:13 -0700739 return this;
Adam Powellcf78b3e2010-09-12 18:25:23 -0700740 }
Adam Powell8d02dea2011-05-31 21:35:13 -0700741
742 @Override
743 public MenuItem setShowAsActionFlags(int actionEnum) {
744 setShowAsAction(actionEnum);
745 return this;
746 }
747
748 @Override
749 public boolean expandActionView() {
Adam Powell2dc27f22013-07-16 11:35:17 -0700750 if (!hasCollapsibleActionView()) {
Adam Powell8d02dea2011-05-31 21:35:13 -0700751 return false;
752 }
753
754 if (mOnActionExpandListener == null ||
755 mOnActionExpandListener.onMenuItemActionExpand(this)) {
756 return mMenu.expandItemActionView(this);
757 }
758
759 return false;
760 }
761
762 @Override
763 public boolean collapseActionView() {
764 if ((mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) == 0) {
765 return false;
766 }
767 if (mActionView == null) {
768 // We're already collapsed if we have no action view.
769 return true;
770 }
771
772 if (mOnActionExpandListener == null ||
773 mOnActionExpandListener.onMenuItemActionCollapse(this)) {
774 return mMenu.collapseItemActionView(this);
775 }
776
777 return false;
778 }
779
780 @Override
781 public MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
782 mOnActionExpandListener = listener;
783 return this;
784 }
785
786 public boolean hasCollapsibleActionView() {
Adam Powellb4c8ba42013-07-11 16:17:10 -0700787 if ((mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) != 0) {
788 if (mActionView == null && mActionProvider != null) {
789 mActionView = mActionProvider.onCreateActionView(this);
790 }
791 return mActionView != null;
792 }
793 return false;
Adam Powell8d02dea2011-05-31 21:35:13 -0700794 }
795
796 public void setActionViewExpanded(boolean isExpanded) {
797 mIsActionViewExpanded = isExpanded;
798 mMenu.onItemsChanged(false);
799 }
800
801 public boolean isActionViewExpanded() {
802 return mIsActionViewExpanded;
803 }
Vladislav Kaznacheev7039cbc2017-01-04 10:15:31 -0800804
805 @Override
806 public MenuItem setContentDescription(CharSequence contentDescription) {
807 mContentDescription = contentDescription;
808
809 mMenu.onItemsChanged(false);
810
811 return this;
812 }
813
814 @Override
815 public CharSequence getContentDescription() {
816 return mContentDescription;
817 }
818
819 @Override
Vladislav Kaznacheev6a944ca2017-01-19 11:02:12 -0800820 public MenuItem setTooltipText(CharSequence tooltipText) {
821 mTooltipText = tooltipText;
Vladislav Kaznacheev7039cbc2017-01-04 10:15:31 -0800822
823 mMenu.onItemsChanged(false);
824
825 return this;
826 }
827
828 @Override
Vladislav Kaznacheev6a944ca2017-01-19 11:02:12 -0800829 public CharSequence getTooltipText() {
830 return mTooltipText;
Vladislav Kaznacheev7039cbc2017-01-04 10:15:31 -0800831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832}