Home | History | Annotate | Download | only in menu
      1 /*
      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 
     17 package com.android.internal.view.menu;
     18 
     19 import android.content.Context;
     20 import android.content.res.TypedArray;
     21 import android.graphics.drawable.Drawable;
     22 import android.util.AttributeSet;
     23 import android.view.LayoutInflater;
     24 import android.view.View;
     25 import android.view.ViewGroup;
     26 import android.view.accessibility.AccessibilityNodeInfo;
     27 import android.widget.CheckBox;
     28 import android.widget.CompoundButton;
     29 import android.widget.ImageView;
     30 import android.widget.LinearLayout;
     31 import android.widget.RadioButton;
     32 import android.widget.TextView;
     33 
     34 /**
     35  * The item view for each item in the ListView-based MenuViews.
     36  */
     37 public class ListMenuItemView extends LinearLayout implements MenuView.ItemView {
     38     private static final String TAG = "ListMenuItemView";
     39     private MenuItemImpl mItemData;
     40 
     41     private ImageView mIconView;
     42     private RadioButton mRadioButton;
     43     private TextView mTitleView;
     44     private CheckBox mCheckBox;
     45     private TextView mShortcutView;
     46 
     47     private Drawable mBackground;
     48     private int mTextAppearance;
     49     private Context mTextAppearanceContext;
     50     private boolean mPreserveIconSpacing;
     51 
     52     private int mMenuType;
     53 
     54     private LayoutInflater mInflater;
     55 
     56     private boolean mForceShowIcon;
     57 
     58     public ListMenuItemView(
     59             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
     60         super(context, attrs, defStyleAttr, defStyleRes);
     61 
     62         final TypedArray a = context.obtainStyledAttributes(
     63                 attrs, com.android.internal.R.styleable.MenuView, defStyleAttr, defStyleRes);
     64 
     65         mBackground = a.getDrawable(com.android.internal.R.styleable.MenuView_itemBackground);
     66         mTextAppearance = a.getResourceId(com.android.internal.R.styleable.
     67                                           MenuView_itemTextAppearance, -1);
     68         mPreserveIconSpacing = a.getBoolean(
     69                 com.android.internal.R.styleable.MenuView_preserveIconSpacing, false);
     70         mTextAppearanceContext = context;
     71 
     72         a.recycle();
     73     }
     74 
     75     public ListMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) {
     76         this(context, attrs, defStyleAttr, 0);
     77     }
     78 
     79     public ListMenuItemView(Context context, AttributeSet attrs) {
     80         this(context, attrs, 0);
     81     }
     82 
     83     @Override
     84     protected void onFinishInflate() {
     85         super.onFinishInflate();
     86 
     87         setBackgroundDrawable(mBackground);
     88 
     89         mTitleView = (TextView) findViewById(com.android.internal.R.id.title);
     90         if (mTextAppearance != -1) {
     91             mTitleView.setTextAppearance(mTextAppearanceContext,
     92                                          mTextAppearance);
     93         }
     94 
     95         mShortcutView = (TextView) findViewById(com.android.internal.R.id.shortcut);
     96     }
     97 
     98     public void initialize(MenuItemImpl itemData, int menuType) {
     99         mItemData = itemData;
    100         mMenuType = menuType;
    101 
    102         setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
    103 
    104         setTitle(itemData.getTitleForItemView(this));
    105         setCheckable(itemData.isCheckable());
    106         setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut());
    107         setIcon(itemData.getIcon());
    108         setEnabled(itemData.isEnabled());
    109     }
    110 
    111     public void setForceShowIcon(boolean forceShow) {
    112         mPreserveIconSpacing = mForceShowIcon = forceShow;
    113     }
    114 
    115     public void setTitle(CharSequence title) {
    116         if (title != null) {
    117             mTitleView.setText(title);
    118 
    119             if (mTitleView.getVisibility() != VISIBLE) mTitleView.setVisibility(VISIBLE);
    120         } else {
    121             if (mTitleView.getVisibility() != GONE) mTitleView.setVisibility(GONE);
    122         }
    123     }
    124 
    125     public MenuItemImpl getItemData() {
    126         return mItemData;
    127     }
    128 
    129     public void setCheckable(boolean checkable) {
    130         if (!checkable && mRadioButton == null && mCheckBox == null) {
    131             return;
    132         }
    133 
    134         // Depending on whether its exclusive check or not, the checkbox or
    135         // radio button will be the one in use (and the other will be otherCompoundButton)
    136         final CompoundButton compoundButton;
    137         final CompoundButton otherCompoundButton;
    138 
    139         if (mItemData.isExclusiveCheckable()) {
    140             if (mRadioButton == null) {
    141                 insertRadioButton();
    142             }
    143             compoundButton = mRadioButton;
    144             otherCompoundButton = mCheckBox;
    145         } else {
    146             if (mCheckBox == null) {
    147                 insertCheckBox();
    148             }
    149             compoundButton = mCheckBox;
    150             otherCompoundButton = mRadioButton;
    151         }
    152 
    153         if (checkable) {
    154             compoundButton.setChecked(mItemData.isChecked());
    155 
    156             final int newVisibility = checkable ? VISIBLE : GONE;
    157             if (compoundButton.getVisibility() != newVisibility) {
    158                 compoundButton.setVisibility(newVisibility);
    159             }
    160 
    161             // Make sure the other compound button isn't visible
    162             if (otherCompoundButton != null && otherCompoundButton.getVisibility() != GONE) {
    163                 otherCompoundButton.setVisibility(GONE);
    164             }
    165         } else {
    166             if (mCheckBox != null) mCheckBox.setVisibility(GONE);
    167             if (mRadioButton != null) mRadioButton.setVisibility(GONE);
    168         }
    169     }
    170 
    171     public void setChecked(boolean checked) {
    172         CompoundButton compoundButton;
    173 
    174         if (mItemData.isExclusiveCheckable()) {
    175             if (mRadioButton == null) {
    176                 insertRadioButton();
    177             }
    178             compoundButton = mRadioButton;
    179         } else {
    180             if (mCheckBox == null) {
    181                 insertCheckBox();
    182             }
    183             compoundButton = mCheckBox;
    184         }
    185 
    186         compoundButton.setChecked(checked);
    187     }
    188 
    189     public void setShortcut(boolean showShortcut, char shortcutKey) {
    190         final int newVisibility = (showShortcut && mItemData.shouldShowShortcut())
    191                 ? VISIBLE : GONE;
    192 
    193         if (newVisibility == VISIBLE) {
    194             mShortcutView.setText(mItemData.getShortcutLabel());
    195         }
    196 
    197         if (mShortcutView.getVisibility() != newVisibility) {
    198             mShortcutView.setVisibility(newVisibility);
    199         }
    200     }
    201 
    202     public void setIcon(Drawable icon) {
    203         final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon;
    204         if (!showIcon && !mPreserveIconSpacing) {
    205             return;
    206         }
    207 
    208         if (mIconView == null && icon == null && !mPreserveIconSpacing) {
    209             return;
    210         }
    211 
    212         if (mIconView == null) {
    213             insertIconView();
    214         }
    215 
    216         if (icon != null || mPreserveIconSpacing) {
    217             mIconView.setImageDrawable(showIcon ? icon : null);
    218 
    219             if (mIconView.getVisibility() != VISIBLE) {
    220                 mIconView.setVisibility(VISIBLE);
    221             }
    222         } else {
    223             mIconView.setVisibility(GONE);
    224         }
    225     }
    226 
    227     @Override
    228     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    229         if (mIconView != null && mPreserveIconSpacing) {
    230             // Enforce minimum icon spacing
    231             ViewGroup.LayoutParams lp = getLayoutParams();
    232             LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
    233             if (lp.height > 0 && iconLp.width <= 0) {
    234                 iconLp.width = lp.height;
    235             }
    236         }
    237         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    238     }
    239 
    240     private void insertIconView() {
    241         LayoutInflater inflater = getInflater();
    242         mIconView = (ImageView) inflater.inflate(com.android.internal.R.layout.list_menu_item_icon,
    243                 this, false);
    244         addView(mIconView, 0);
    245     }
    246 
    247     private void insertRadioButton() {
    248         LayoutInflater inflater = getInflater();
    249         mRadioButton =
    250                 (RadioButton) inflater.inflate(com.android.internal.R.layout.list_menu_item_radio,
    251                 this, false);
    252         addView(mRadioButton);
    253     }
    254 
    255     private void insertCheckBox() {
    256         LayoutInflater inflater = getInflater();
    257         mCheckBox =
    258                 (CheckBox) inflater.inflate(com.android.internal.R.layout.list_menu_item_checkbox,
    259                 this, false);
    260         addView(mCheckBox);
    261     }
    262 
    263     public boolean prefersCondensedTitle() {
    264         return false;
    265     }
    266 
    267     public boolean showsIcon() {
    268         return mForceShowIcon;
    269     }
    270 
    271     private LayoutInflater getInflater() {
    272         if (mInflater == null) {
    273             mInflater = LayoutInflater.from(mContext);
    274         }
    275         return mInflater;
    276     }
    277 
    278     @Override
    279     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
    280         super.onInitializeAccessibilityNodeInfo(info);
    281 
    282         if (mItemData != null && mItemData.hasSubMenu()) {
    283             info.setCanOpenPopup(true);
    284         }
    285     }
    286 }
    287