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