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.android.internal.view.menu; 18 19 import android.annotation.Nullable; 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.res.ColorStateList; 24 import android.graphics.PorterDuff; 25 import android.graphics.drawable.Drawable; 26 import android.os.Build; 27 import android.view.ActionProvider; 28 import android.view.ContextMenu.ContextMenuInfo; 29 import android.view.KeyEvent; 30 import android.view.MenuItem; 31 import android.view.SubMenu; 32 import android.view.View; 33 34 /** 35 * @hide 36 */ 37 public class ActionMenuItem implements MenuItem { 38 private final int mId; 39 private final int mGroup; 40 private final int mCategoryOrder; 41 private final int mOrdering; 42 43 private CharSequence mTitle; 44 private CharSequence mTitleCondensed; 45 private Intent mIntent; 46 private char mShortcutNumericChar; 47 private int mShortcutNumericModifiers = KeyEvent.META_CTRL_ON; 48 private char mShortcutAlphabeticChar; 49 private int mShortcutAlphabeticModifiers = KeyEvent.META_CTRL_ON; 50 51 private Drawable mIconDrawable; 52 private int mIconResId = NO_ICON; 53 private ColorStateList mIconTintList = null; 54 private PorterDuff.Mode mIconTintMode = null; 55 private boolean mHasIconTint = false; 56 private boolean mHasIconTintMode = false; 57 58 private Context mContext; 59 60 private MenuItem.OnMenuItemClickListener mClickListener; 61 62 private CharSequence mContentDescription; 63 private CharSequence mTooltipText; 64 65 private static final int NO_ICON = 0; 66 67 private int mFlags = ENABLED; 68 private static final int CHECKABLE = 0x00000001; 69 private static final int CHECKED = 0x00000002; 70 private static final int EXCLUSIVE = 0x00000004; 71 private static final int HIDDEN = 0x00000008; 72 private static final int ENABLED = 0x00000010; 73 74 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) ActionMenuItem(Context context, int group, int id, int categoryOrder, int ordering, CharSequence title)75 public ActionMenuItem(Context context, int group, int id, int categoryOrder, int ordering, 76 CharSequence title) { 77 mContext = context; 78 mId = id; 79 mGroup = group; 80 mCategoryOrder = categoryOrder; 81 mOrdering = ordering; 82 mTitle = title; 83 } 84 getAlphabeticShortcut()85 public char getAlphabeticShortcut() { 86 return mShortcutAlphabeticChar; 87 } 88 getAlphabeticModifiers()89 public int getAlphabeticModifiers() { 90 return mShortcutAlphabeticModifiers; 91 } 92 getGroupId()93 public int getGroupId() { 94 return mGroup; 95 } 96 getIcon()97 public Drawable getIcon() { 98 return mIconDrawable; 99 } 100 getIntent()101 public Intent getIntent() { 102 return mIntent; 103 } 104 getItemId()105 public int getItemId() { 106 return mId; 107 } 108 getMenuInfo()109 public ContextMenuInfo getMenuInfo() { 110 return null; 111 } 112 getNumericShortcut()113 public char getNumericShortcut() { 114 return mShortcutNumericChar; 115 } 116 getNumericModifiers()117 public int getNumericModifiers() { 118 return mShortcutNumericModifiers; 119 } 120 getOrder()121 public int getOrder() { 122 return mOrdering; 123 } 124 getSubMenu()125 public SubMenu getSubMenu() { 126 return null; 127 } 128 getTitle()129 public CharSequence getTitle() { 130 return mTitle; 131 } 132 getTitleCondensed()133 public CharSequence getTitleCondensed() { 134 return mTitleCondensed != null ? mTitleCondensed : mTitle; 135 } 136 hasSubMenu()137 public boolean hasSubMenu() { 138 return false; 139 } 140 isCheckable()141 public boolean isCheckable() { 142 return (mFlags & CHECKABLE) != 0; 143 } 144 isChecked()145 public boolean isChecked() { 146 return (mFlags & CHECKED) != 0; 147 } 148 isEnabled()149 public boolean isEnabled() { 150 return (mFlags & ENABLED) != 0; 151 } 152 isVisible()153 public boolean isVisible() { 154 return (mFlags & HIDDEN) == 0; 155 } 156 setAlphabeticShortcut(char alphaChar)157 public MenuItem setAlphabeticShortcut(char alphaChar) { 158 mShortcutAlphabeticChar = Character.toLowerCase(alphaChar); 159 return this; 160 } 161 setAlphabeticShortcut(char alphachar, int alphaModifiers)162 public MenuItem setAlphabeticShortcut(char alphachar, int alphaModifiers) { 163 mShortcutAlphabeticChar = Character.toLowerCase(alphachar); 164 mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers); 165 return this; 166 } 167 setCheckable(boolean checkable)168 public MenuItem setCheckable(boolean checkable) { 169 mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0); 170 return this; 171 } 172 setExclusiveCheckable(boolean exclusive)173 public ActionMenuItem setExclusiveCheckable(boolean exclusive) { 174 mFlags = (mFlags & ~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0); 175 return this; 176 } 177 setChecked(boolean checked)178 public MenuItem setChecked(boolean checked) { 179 mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0); 180 return this; 181 } 182 setEnabled(boolean enabled)183 public MenuItem setEnabled(boolean enabled) { 184 mFlags = (mFlags & ~ENABLED) | (enabled ? ENABLED : 0); 185 return this; 186 } 187 setIcon(Drawable icon)188 public MenuItem setIcon(Drawable icon) { 189 mIconDrawable = icon; 190 mIconResId = NO_ICON; 191 192 applyIconTint(); 193 return this; 194 } 195 setIcon(int iconRes)196 public MenuItem setIcon(int iconRes) { 197 mIconResId = iconRes; 198 mIconDrawable = mContext.getDrawable(iconRes); 199 200 applyIconTint(); 201 return this; 202 } 203 204 @Override setIconTintList(@ullable ColorStateList iconTintList)205 public MenuItem setIconTintList(@Nullable ColorStateList iconTintList) { 206 mIconTintList = iconTintList; 207 mHasIconTint = true; 208 209 applyIconTint(); 210 211 return this; 212 } 213 214 @Nullable 215 @Override getIconTintList()216 public ColorStateList getIconTintList() { 217 return mIconTintList; 218 } 219 220 @Override setIconTintMode(PorterDuff.Mode iconTintMode)221 public MenuItem setIconTintMode(PorterDuff.Mode iconTintMode) { 222 mIconTintMode = iconTintMode; 223 mHasIconTintMode = true; 224 225 applyIconTint(); 226 227 return this; 228 } 229 230 @Nullable 231 @Override getIconTintMode()232 public PorterDuff.Mode getIconTintMode() { 233 return mIconTintMode; 234 } 235 applyIconTint()236 private void applyIconTint() { 237 if (mIconDrawable != null && (mHasIconTint || mHasIconTintMode)) { 238 mIconDrawable = mIconDrawable.mutate(); 239 240 if (mHasIconTint) { 241 mIconDrawable.setTintList(mIconTintList); 242 } 243 244 if (mHasIconTintMode) { 245 mIconDrawable.setTintMode(mIconTintMode); 246 } 247 } 248 } 249 setIntent(Intent intent)250 public MenuItem setIntent(Intent intent) { 251 mIntent = intent; 252 return this; 253 } 254 setNumericShortcut(char numericChar)255 public MenuItem setNumericShortcut(char numericChar) { 256 mShortcutNumericChar = numericChar; 257 return this; 258 } 259 setNumericShortcut(char numericChar, int numericModifiers)260 public MenuItem setNumericShortcut(char numericChar, int numericModifiers) { 261 mShortcutNumericChar = numericChar; 262 mShortcutNumericModifiers = KeyEvent.normalizeMetaState(numericModifiers); 263 return this; 264 } 265 setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener)266 public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) { 267 mClickListener = menuItemClickListener; 268 return this; 269 } 270 setShortcut(char numericChar, char alphaChar)271 public MenuItem setShortcut(char numericChar, char alphaChar) { 272 mShortcutNumericChar = numericChar; 273 mShortcutAlphabeticChar = Character.toLowerCase(alphaChar); 274 return this; 275 } 276 setShortcut(char numericChar, char alphaChar, int numericModifiers, int alphaModifiers)277 public MenuItem setShortcut(char numericChar, char alphaChar, int numericModifiers, 278 int alphaModifiers) { 279 mShortcutNumericChar = numericChar; 280 mShortcutNumericModifiers = KeyEvent.normalizeMetaState(numericModifiers); 281 mShortcutAlphabeticChar = Character.toLowerCase(alphaChar); 282 mShortcutAlphabeticModifiers = KeyEvent.normalizeMetaState(alphaModifiers); 283 return this; 284 } 285 setTitle(CharSequence title)286 public MenuItem setTitle(CharSequence title) { 287 mTitle = title; 288 return this; 289 } 290 setTitle(int title)291 public MenuItem setTitle(int title) { 292 mTitle = mContext.getResources().getString(title); 293 return this; 294 } 295 setTitleCondensed(CharSequence title)296 public MenuItem setTitleCondensed(CharSequence title) { 297 mTitleCondensed = title; 298 return this; 299 } 300 setVisible(boolean visible)301 public MenuItem setVisible(boolean visible) { 302 mFlags = (mFlags & HIDDEN) | (visible ? 0 : HIDDEN); 303 return this; 304 } 305 invoke()306 public boolean invoke() { 307 if (mClickListener != null && mClickListener.onMenuItemClick(this)) { 308 return true; 309 } 310 311 if (mIntent != null) { 312 mContext.startActivity(mIntent); 313 return true; 314 } 315 316 return false; 317 } 318 setShowAsAction(int show)319 public void setShowAsAction(int show) { 320 // Do nothing. ActionMenuItems always show as action buttons. 321 } 322 setActionView(View actionView)323 public MenuItem setActionView(View actionView) { 324 throw new UnsupportedOperationException(); 325 } 326 getActionView()327 public View getActionView() { 328 return null; 329 } 330 331 @Override setActionView(int resId)332 public MenuItem setActionView(int resId) { 333 throw new UnsupportedOperationException(); 334 } 335 336 @Override getActionProvider()337 public ActionProvider getActionProvider() { 338 return null; 339 } 340 341 @Override setActionProvider(ActionProvider actionProvider)342 public MenuItem setActionProvider(ActionProvider actionProvider) { 343 throw new UnsupportedOperationException(); 344 } 345 346 @Override setShowAsActionFlags(int actionEnum)347 public MenuItem setShowAsActionFlags(int actionEnum) { 348 setShowAsAction(actionEnum); 349 return this; 350 } 351 352 @Override expandActionView()353 public boolean expandActionView() { 354 return false; 355 } 356 357 @Override collapseActionView()358 public boolean collapseActionView() { 359 return false; 360 } 361 362 @Override isActionViewExpanded()363 public boolean isActionViewExpanded() { 364 return false; 365 } 366 367 @Override setOnActionExpandListener(OnActionExpandListener listener)368 public MenuItem setOnActionExpandListener(OnActionExpandListener listener) { 369 // No need to save the listener; ActionMenuItem does not support collapsing items. 370 return this; 371 } 372 373 @Override setContentDescription(CharSequence contentDescription)374 public MenuItem setContentDescription(CharSequence contentDescription) { 375 mContentDescription = contentDescription; 376 return this; 377 } 378 379 @Override getContentDescription()380 public CharSequence getContentDescription() { 381 return mContentDescription; 382 } 383 384 @Override setTooltipText(CharSequence tooltipText)385 public MenuItem setTooltipText(CharSequence tooltipText) { 386 mTooltipText = tooltipText; 387 return this; 388 } 389 390 @Override getTooltipText()391 public CharSequence getTooltipText() { 392 return mTooltipText; 393 } 394 } 395