Home | History | Annotate | Download | only in menu
      1 /*
      2  * Copyright (C) 2012 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.util.Log;
     27 import android.view.ContextMenu;
     28 import android.view.MenuItem;
     29 import android.view.SubMenu;
     30 import android.view.View;
     31 import android.widget.FrameLayout;
     32 
     33 import androidx.annotation.RestrictTo;
     34 import androidx.appcompat.view.CollapsibleActionView;
     35 import androidx.core.internal.view.SupportMenuItem;
     36 import androidx.core.view.ActionProvider;
     37 
     38 import java.lang.reflect.Method;
     39 
     40 /**
     41  * Wraps a support {@link SupportMenuItem} as a framework {@link android.view.MenuItem}
     42  * @hide
     43  */
     44 @RestrictTo(LIBRARY_GROUP)
     45 public class MenuItemWrapperICS extends BaseMenuWrapper<SupportMenuItem> implements MenuItem {
     46     static final String LOG_TAG = "MenuItemWrapper";
     47 
     48     // Reflection Method to call setExclusiveCheckable
     49     private Method mSetExclusiveCheckableMethod;
     50 
     51     MenuItemWrapperICS(Context context, SupportMenuItem object) {
     52         super(context, object);
     53     }
     54 
     55     @Override
     56     public int getItemId() {
     57         return mWrappedObject.getItemId();
     58     }
     59 
     60     @Override
     61     public int getGroupId() {
     62         return mWrappedObject.getGroupId();
     63     }
     64 
     65     @Override
     66     public int getOrder() {
     67         return mWrappedObject.getOrder();
     68     }
     69 
     70     @Override
     71     public MenuItem setTitle(CharSequence title) {
     72         mWrappedObject.setTitle(title);
     73         return this;
     74     }
     75 
     76     @Override
     77     public MenuItem setTitle(int title) {
     78         mWrappedObject.setTitle(title);
     79         return this;
     80     }
     81 
     82     @Override
     83     public CharSequence getTitle() {
     84         return mWrappedObject.getTitle();
     85     }
     86 
     87     @Override
     88     public MenuItem setTitleCondensed(CharSequence title) {
     89         mWrappedObject.setTitleCondensed(title);
     90         return this;
     91     }
     92 
     93     @Override
     94     public CharSequence getTitleCondensed() {
     95         return mWrappedObject.getTitleCondensed();
     96     }
     97 
     98     @Override
     99     public MenuItem setIcon(Drawable icon) {
    100         mWrappedObject.setIcon(icon);
    101         return this;
    102     }
    103 
    104     @Override
    105     public MenuItem setIcon(int iconRes) {
    106         mWrappedObject.setIcon(iconRes);
    107         return this;
    108     }
    109 
    110     @Override
    111     public Drawable getIcon() {
    112         return mWrappedObject.getIcon();
    113     }
    114 
    115     @Override
    116     public MenuItem setIntent(Intent intent) {
    117         mWrappedObject.setIntent(intent);
    118         return this;
    119     }
    120 
    121     @Override
    122     public Intent getIntent() {
    123         return mWrappedObject.getIntent();
    124     }
    125 
    126     @Override
    127     public MenuItem setShortcut(char numericChar, char alphaChar) {
    128         mWrappedObject.setShortcut(numericChar, alphaChar);
    129         return this;
    130     }
    131 
    132     @Override
    133     public MenuItem setShortcut(char numericChar, char alphaChar, int numericModifiers,
    134             int alphaModifiers) {
    135         mWrappedObject.setShortcut(numericChar, alphaChar, numericModifiers, alphaModifiers);
    136         return this;
    137     }
    138 
    139     @Override
    140     public MenuItem setNumericShortcut(char numericChar) {
    141         mWrappedObject.setNumericShortcut(numericChar);
    142         return this;
    143     }
    144 
    145     @Override
    146     public MenuItem setNumericShortcut(char numericChar, int numericModifiers) {
    147         mWrappedObject.setNumericShortcut(numericChar, numericModifiers);
    148         return this;
    149     }
    150 
    151     @Override
    152     public char getNumericShortcut() {
    153         return mWrappedObject.getNumericShortcut();
    154     }
    155 
    156     @Override
    157     public int getNumericModifiers() {
    158         return mWrappedObject.getNumericModifiers();
    159     }
    160 
    161     @Override
    162     public MenuItem setAlphabeticShortcut(char alphaChar) {
    163         mWrappedObject.setAlphabeticShortcut(alphaChar);
    164         return this;
    165     }
    166 
    167     @Override
    168     public MenuItem setAlphabeticShortcut(char alphaChar, int alphaModifiers) {
    169         mWrappedObject.setAlphabeticShortcut(alphaChar, alphaModifiers);
    170         return this;
    171     }
    172 
    173     @Override
    174     public char getAlphabeticShortcut() {
    175         return mWrappedObject.getAlphabeticShortcut();
    176     }
    177 
    178     @Override
    179     public int getAlphabeticModifiers() {
    180         return mWrappedObject.getAlphabeticModifiers();
    181     }
    182 
    183     @Override
    184     public MenuItem setCheckable(boolean checkable) {
    185         mWrappedObject.setCheckable(checkable);
    186         return this;
    187     }
    188 
    189     @Override
    190     public boolean isCheckable() {
    191         return mWrappedObject.isCheckable();
    192     }
    193 
    194     @Override
    195     public MenuItem setChecked(boolean checked) {
    196         mWrappedObject.setChecked(checked);
    197         return this;
    198     }
    199 
    200     @Override
    201     public boolean isChecked() {
    202         return mWrappedObject.isChecked();
    203     }
    204 
    205     @Override
    206     public MenuItem setVisible(boolean visible) {
    207         return mWrappedObject.setVisible(visible);
    208     }
    209 
    210     @Override
    211     public boolean isVisible() {
    212         return mWrappedObject.isVisible();
    213     }
    214 
    215     @Override
    216     public MenuItem setEnabled(boolean enabled) {
    217         mWrappedObject.setEnabled(enabled);
    218         return this;
    219     }
    220 
    221     @Override
    222     public boolean isEnabled() {
    223         return mWrappedObject.isEnabled();
    224     }
    225 
    226     @Override
    227     public boolean hasSubMenu() {
    228         return mWrappedObject.hasSubMenu();
    229     }
    230 
    231     @Override
    232     public SubMenu getSubMenu() {
    233         return getSubMenuWrapper(mWrappedObject.getSubMenu());
    234     }
    235 
    236     @Override
    237     public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) {
    238         mWrappedObject.setOnMenuItemClickListener(menuItemClickListener != null ?
    239                 new OnMenuItemClickListenerWrapper(menuItemClickListener) : null);
    240         return this;
    241     }
    242 
    243     @Override
    244     public ContextMenu.ContextMenuInfo getMenuInfo() {
    245         return mWrappedObject.getMenuInfo();
    246     }
    247 
    248     @Override
    249     public void setShowAsAction(int actionEnum) {
    250         mWrappedObject.setShowAsAction(actionEnum);
    251     }
    252 
    253     @Override
    254     public MenuItem setShowAsActionFlags(int actionEnum) {
    255         mWrappedObject.setShowAsActionFlags(actionEnum);
    256         return this;
    257     }
    258 
    259     @Override
    260     public MenuItem setActionView(View view) {
    261         if (view instanceof android.view.CollapsibleActionView) {
    262             view = new CollapsibleActionViewWrapper(view);
    263         }
    264         mWrappedObject.setActionView(view);
    265         return this;
    266     }
    267 
    268     @Override
    269     public MenuItem setActionView(int resId) {
    270         // Make framework menu item inflate the view
    271         mWrappedObject.setActionView(resId);
    272 
    273         View actionView = mWrappedObject.getActionView();
    274         if (actionView instanceof android.view.CollapsibleActionView) {
    275             // If the inflated Action View is support-collapsible, wrap it
    276             mWrappedObject.setActionView(new CollapsibleActionViewWrapper(actionView));
    277         }
    278         return this;
    279     }
    280 
    281     @Override
    282     public View getActionView() {
    283         View actionView = mWrappedObject.getActionView();
    284         if (actionView instanceof CollapsibleActionViewWrapper) {
    285             return ((CollapsibleActionViewWrapper) actionView).getWrappedView();
    286         }
    287         return actionView;
    288     }
    289 
    290     @Override
    291     public MenuItem setActionProvider(android.view.ActionProvider provider) {
    292         mWrappedObject.setSupportActionProvider(
    293                 provider != null ? createActionProviderWrapper(provider) : null);
    294         return this;
    295     }
    296 
    297     @Override
    298     public android.view.ActionProvider getActionProvider() {
    299         ActionProvider provider = mWrappedObject.getSupportActionProvider();
    300         if (provider instanceof ActionProviderWrapper) {
    301             return ((ActionProviderWrapper) provider).mInner;
    302         }
    303         return null;
    304     }
    305 
    306     @Override
    307     public boolean expandActionView() {
    308         return mWrappedObject.expandActionView();
    309     }
    310 
    311     @Override
    312     public boolean collapseActionView() {
    313         return mWrappedObject.collapseActionView();
    314     }
    315 
    316     @Override
    317     public boolean isActionViewExpanded() {
    318         return mWrappedObject.isActionViewExpanded();
    319     }
    320 
    321     @Override
    322     public MenuItem setOnActionExpandListener(MenuItem.OnActionExpandListener listener) {
    323         mWrappedObject.setOnActionExpandListener(listener != null
    324                 ? new OnActionExpandListenerWrapper(listener) : null);
    325         return this;
    326     }
    327 
    328     @Override
    329     public MenuItem setContentDescription(CharSequence contentDescription) {
    330         mWrappedObject.setContentDescription(contentDescription);
    331         return this;
    332     }
    333 
    334     @Override
    335     public CharSequence getContentDescription() {
    336         return mWrappedObject.getContentDescription();
    337     }
    338 
    339     @Override
    340     public MenuItem setTooltipText(CharSequence tooltipText) {
    341         mWrappedObject.setTooltipText(tooltipText);
    342         return this;
    343     }
    344 
    345     @Override
    346     public CharSequence getTooltipText() {
    347         return mWrappedObject.getTooltipText();
    348     }
    349 
    350     @Override
    351     public MenuItem setIconTintList(ColorStateList tint) {
    352         mWrappedObject.setIconTintList(tint);
    353         return this;
    354     }
    355 
    356     @Override
    357     public ColorStateList getIconTintList() {
    358         return mWrappedObject.getIconTintList();
    359     }
    360 
    361     @Override
    362     public MenuItem setIconTintMode(PorterDuff.Mode tintMode) {
    363         mWrappedObject.setIconTintMode(tintMode);
    364         return this;
    365     }
    366 
    367     @Override
    368     public PorterDuff.Mode getIconTintMode() {
    369         return mWrappedObject.getIconTintMode();
    370     }
    371 
    372     public void setExclusiveCheckable(boolean checkable) {
    373         try {
    374             if (mSetExclusiveCheckableMethod == null) {
    375                 mSetExclusiveCheckableMethod = mWrappedObject.getClass()
    376                         .getDeclaredMethod("setExclusiveCheckable", Boolean.TYPE);
    377             }
    378             mSetExclusiveCheckableMethod.invoke(mWrappedObject, checkable);
    379         } catch (Exception e) {
    380             Log.w(LOG_TAG, "Error while calling setExclusiveCheckable", e);
    381         }
    382     }
    383 
    384     ActionProviderWrapper createActionProviderWrapper(android.view.ActionProvider provider) {
    385         return new ActionProviderWrapper(mContext, provider);
    386     }
    387 
    388     private class OnMenuItemClickListenerWrapper extends BaseWrapper<OnMenuItemClickListener>
    389             implements android.view.MenuItem.OnMenuItemClickListener {
    390 
    391         OnMenuItemClickListenerWrapper(OnMenuItemClickListener object) {
    392             super(object);
    393         }
    394 
    395         @Override
    396         public boolean onMenuItemClick(android.view.MenuItem item) {
    397             return mWrappedObject.onMenuItemClick(getMenuItemWrapper(item));
    398         }
    399     }
    400 
    401     private class OnActionExpandListenerWrapper extends BaseWrapper<MenuItem.OnActionExpandListener>
    402             implements MenuItem.OnActionExpandListener {
    403 
    404         OnActionExpandListenerWrapper(MenuItem.OnActionExpandListener object) {
    405             super(object);
    406         }
    407 
    408         @Override
    409         public boolean onMenuItemActionExpand(android.view.MenuItem item) {
    410             return mWrappedObject.onMenuItemActionExpand(getMenuItemWrapper(item));
    411         }
    412 
    413         @Override
    414         public boolean onMenuItemActionCollapse(android.view.MenuItem item) {
    415             return mWrappedObject.onMenuItemActionCollapse(getMenuItemWrapper(item));
    416         }
    417     }
    418 
    419     class ActionProviderWrapper extends androidx.core.view.ActionProvider {
    420         final android.view.ActionProvider mInner;
    421 
    422         public ActionProviderWrapper(Context context, android.view.ActionProvider inner) {
    423             super(context);
    424             mInner = inner;
    425         }
    426 
    427         @Override
    428         public View onCreateActionView() {
    429             return mInner.onCreateActionView();
    430         }
    431 
    432         @Override
    433         public boolean onPerformDefaultAction() {
    434             return mInner.onPerformDefaultAction();
    435         }
    436 
    437         @Override
    438         public boolean hasSubMenu() {
    439             return mInner.hasSubMenu();
    440         }
    441 
    442         @Override
    443         public void onPrepareSubMenu(android.view.SubMenu subMenu) {
    444             mInner.onPrepareSubMenu(getSubMenuWrapper(subMenu));
    445         }
    446     }
    447 
    448     /**
    449      * Wrap a support {@link androidx.appcompat.view.CollapsibleActionView} into a framework
    450      * {@link android.view.CollapsibleActionView}.
    451      */
    452     static class CollapsibleActionViewWrapper extends FrameLayout
    453             implements CollapsibleActionView {
    454 
    455         final android.view.CollapsibleActionView mWrappedView;
    456 
    457         CollapsibleActionViewWrapper(View actionView) {
    458             super(actionView.getContext());
    459             mWrappedView = (android.view.CollapsibleActionView) actionView;
    460             addView(actionView);
    461         }
    462 
    463         @Override
    464         public void onActionViewExpanded() {
    465             mWrappedView.onActionViewExpanded();
    466         }
    467 
    468         @Override
    469         public void onActionViewCollapsed() {
    470             mWrappedView.onActionViewCollapsed();
    471         }
    472 
    473         View getWrappedView() {
    474             return (View) mWrappedView;
    475         }
    476     }
    477 }
    478