content: /*
   * Copyright (C) 2006 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.internal.view.menu;
  
  import com.android.internal.view.menu.MenuBuilder.ItemInvoker;
  
  import android.annotation.UnsupportedAppUsage;
  import android.content.Context;
  import android.content.res.TypedArray;
  import android.graphics.Rect;
  import android.graphics.drawable.Drawable;
  import android.text.TextUtils;
  import android.util.AttributeSet;
  import android.view.Gravity;
  import android.view.SoundEffectConstants;
  import android.view.View;
  import android.view.ViewDebug;
  import android.widget.TextView;
  import android.text.Layout;
  
  /**
   * The item view for each item in the {@link IconMenuView}.
   */
  public final class IconMenuItemView extends TextView implements MenuView.ItemView {
      
      private static final int NO_ALPHA = 0xFF;
      
      private IconMenuView mIconMenuView;
      
      private ItemInvoker mItemInvoker;
      private MenuItemImpl mItemData; 
      
      private Drawable mIcon;
      
      private int mTextAppearance;
      private Context mTextAppearanceContext;
      
      private float mDisabledAlpha;
  
      private Rect mPositionIconAvailable = new Rect();
      private Rect mPositionIconOutput = new Rect();
      
      private boolean mShortcutCaptionMode;
      private String mShortcutCaption;
      
      private static String sPrependShortcutLabel;
  
      public IconMenuItemView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
          super(context, attrs, defStyleAttr, defStyleRes);
  
          if (sPrependShortcutLabel == null) {
              /*
               * Views should only be constructed from the UI thread, so no
               * synchronization needed
               */
              sPrependShortcutLabel = getResources().getString(
                      com.android.internal.R.string.prepend_shortcut_label);
          }
  
          final TypedArray a = context.obtainStyledAttributes(
                  attrs, com.android.internal.R.styleable.MenuView, defStyleAttr, defStyleRes);
  
          mDisabledAlpha = a.getFloat(
                  com.android.internal.R.styleable.MenuView_itemIconDisabledAlpha, 0.8f);
          mTextAppearance = a.getResourceId(com.android.internal.R.styleable.
                                            MenuView_itemTextAppearance, -1);
          mTextAppearanceContext = context;
          
          a.recycle();
      }
  
      public IconMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) {
          this(context, attrs, defStyleAttr, 0);
      }
  
      public IconMenuItemView(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      /**
       * Initializes with the provided title and icon
       * @param title The title of this item
       * @param icon The icon of this item
       */
      void initialize(CharSequence title, Drawable icon) {
          setClickable(true);
          setFocusable(true);
  
          if (mTextAppearance != -1) {
              setTextAppearance(mTextAppearanceContext, mTextAppearance);
          }
  
          setTitle(title);
          setIcon(icon);
  
          if (mItemData != null) {
              final CharSequence contentDescription = mItemData.getContentDescription();
              if (TextUtils.isEmpty(contentDescription)) {
                  setContentDescription(title);
              } else {
                  setContentDescription(contentDescription);
              }
              setTooltipText(mItemData.getTooltipText());
          }
      }
  
      public void initialize(MenuItemImpl itemData, int menuType) {
          mItemData = itemData;
  
          initialize(itemData.getTitleForItemView(this), itemData.getIcon());
  
          setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
          setEnabled(itemData.isEnabled());
      }
  
      public void setItemData(MenuItemImpl data) {
          mItemData = data;
      }
  
      @Override
      public boolean performClick() {
          // Let the view's click listener have top priority (the More button relies on this)
          if (super.performClick()) {
              return true;
          }
          
          if ((mItemInvoker != null) && (mItemInvoker.invokeItem(mItemData))) {
              playSoundEffect(SoundEffectConstants.CLICK);
              return true;
          } else {
              return false;
          }
      }
      
      public void setTitle(CharSequence title) {
          
          if (mShortcutCaptionMode) {
              /*
               * Don't set the title directly since it will replace the
               * shortcut+title being shown. Instead, re-set the shortcut caption
               * mode so the new title is shown.
               */
              setCaptionMode(true);
              
          } else if (title != null) {
              setText(title);
          }
      }
      
      void setCaptionMode(boolean shortcut) {
          /*
           * If there is no item model, don't do any of the below (for example,
           * the 'More' item doesn't have a model)
           */
          if (mItemData == null) {
              return;
          }
          
          mShortcutCaptionMode = shortcut && (mItemData.shouldShowShortcut());
          
          CharSequence text = mItemData.getTitleForItemView(this);
          
          if (mShortcutCaptionMode) {
              
              if (mShortcutCaption == null) {
                  mShortcutCaption = mItemData.getShortcutLabel();
              }
  
              text = mShortcutCaption;
          }
          
          setText(text);
      }
      
      public void setIcon(Drawable icon) {
          mIcon = icon;
          
          if (icon != null) {
              
              /* Set the bounds of the icon since setCompoundDrawables needs it. */
              icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
              
              // Set the compound drawables
              setCompoundDrawables(null, icon, null, null);
              
              // When there is an icon, make sure the text is at the bottom
              setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
  
              /*
               * Request a layout to reposition the icon. The positioning of icon
               * depends on this TextView's line bounds, which is only available
               * after a layout.
               */  
              requestLayout();
          } else {
              setCompoundDrawables(null, null, null, null);
              
              // When there is no icon, make sure the text is centered vertically
              setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
          }
      }
  
      @UnsupportedAppUsage
      public void setItemInvoker(ItemInvoker itemInvoker) {
          mItemInvoker = itemInvoker;
      }
      
      @ViewDebug.CapturedViewProperty(retrieveReturn = true)
      public MenuItemImpl getItemData() {
          return mItemData;
      }
  
      @Override
      public void setVisibility(int v) {
          super.setVisibility(v);
          
          if (mIconMenuView != null) {
              // On visibility change, mark the IconMenuView to refresh itself eventually
              mIconMenuView.markStaleChildren();
          }
      }
      
      @UnsupportedAppUsage
      void setIconMenuView(IconMenuView iconMenuView) {
          mIconMenuView = iconMenuView;
      }
  
      @Override
      protected void drawableStateChanged() {
          super.drawableStateChanged();
  
          if (mItemData != null && mIcon != null) {
              // When disabled, the not-focused state and the pressed state should
              // drop alpha on the icon
              final boolean isInAlphaState = !mItemData.isEnabled() && (isPressed() || !isFocused());
              mIcon.setAlpha(isInAlphaState ? (int) (mDisabledAlpha * NO_ALPHA) : NO_ALPHA);
          }
      }
  
      @Override
      protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
          super.onLayout(changed, left, top, right, bottom);
          
          positionIcon();
      }
  
      @Override
      protected void onTextChanged(CharSequence text, int start, int before, int after) {
          super.onTextChanged(text, start, before, after);
  
          // our layout params depend on the length of the text
          setLayoutParams(getTextAppropriateLayoutParams());
      }
  
      /**
       * @return layout params appropriate for this view.  If layout params already exist, it will
       *         augment them to be appropriate to the current text size.
       */
      @UnsupportedAppUsage
      IconMenuView.LayoutParams getTextAppropriateLayoutParams() {
          IconMenuView.LayoutParams lp = (IconMenuView.LayoutParams) getLayoutParams();
          if (lp == null) {
              // Default layout parameters
              lp = new IconMenuView.LayoutParams(
                      IconMenuView.LayoutParams.MATCH_PARENT, IconMenuView.LayoutParams.MATCH_PARENT);
          }
  
          // Set the desired width of item
          lp.desiredWidth = (int) Layout.getDesiredWidth(getText(), 0, getText().length(),
                  getPaint(), getTextDirectionHeuristic());
  
          return lp;
      }
  
      /**
       * Positions the icon vertically (horizontal centering is taken care of by
       * the TextView's gravity).
       */
      private void positionIcon() {
          
          if (mIcon == null) {
              return;
          }
          
          // We reuse the output rectangle as a temp rect
          Rect tmpRect = mPositionIconOutput;
          getLineBounds(0, tmpRect);
          mPositionIconAvailable.set(0, 0, getWidth(), tmpRect.top);
          final int layoutDirection = getLayoutDirection();
          Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.START, mIcon.getIntrinsicWidth(), mIcon
                  .getIntrinsicHeight(), mPositionIconAvailable, mPositionIconOutput,
                  layoutDirection);
          mIcon.setBounds(mPositionIconOutput);
      }
  
      public void setCheckable(boolean checkable) {
      }
  
      public void setChecked(boolean checked) {
      }
  
      public void setShortcut(boolean showShortcut, char shortcutKey) {
          
          if (mShortcutCaptionMode) {
              /*
               * Shortcut has changed and we're showing it right now, need to
               * update (clear the old one first).
               */
              mShortcutCaption = null;
              setCaptionMode(true);
          }
      }
  
      public boolean prefersCondensedTitle() {
          return true;
      }
  
      public boolean showsIcon() {
          return true;
      }
  
  }
  