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