content: /*
   * Copyright (C) 2011 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.actionbarsherlock.widget;
  
  import android.os.Build;
  import com.actionbarsherlock.R;
  import com.actionbarsherlock.internal.widget.IcsLinearLayout;
  import com.actionbarsherlock.internal.widget.IcsListPopupWindow;
  import com.actionbarsherlock.view.ActionProvider;
  import com.actionbarsherlock.widget.ActivityChooserModel.ActivityChooserModelClient;
  import android.content.Context;
  import android.content.Intent;
  import android.content.pm.PackageManager;
  import android.content.pm.ResolveInfo;
  import android.content.res.Resources;
  import android.content.res.TypedArray;
  import android.database.DataSetObserver;
  import android.graphics.drawable.Drawable;
  import android.util.AttributeSet;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.ViewTreeObserver;
  import android.view.ViewTreeObserver.OnGlobalLayoutListener;
  import android.widget.AdapterView;
  import android.widget.BaseAdapter;
  import android.widget.FrameLayout;
  import android.widget.ImageView;
  import android.widget.PopupWindow;
  import android.widget.TextView;
  
  /**
   * This class is a view for choosing an activity for handling a given {@link Intent}.
   * <p>
   * The view is composed of two adjacent buttons:
   * <ul>
   * <li>
   * The left button is an immediate action and allows one click activity choosing.
   * Tapping this button immediately executes the intent without requiring any further
   * user input. Long press on this button shows a popup for changing the default
   * activity.
   * </li>
   * <li>
   * The right button is an overflow action and provides an optimized menu
   * of additional activities. Tapping this button shows a popup anchored to this
   * view, listing the most frequently used activities. This list is initially
   * limited to a small number of items in frequency used order. The last item,
   * "Show all..." serves as an affordance to display all available activities.
   * </li>
   * </ul>
   * </p>
   *
   * @hide
   */
  class ActivityChooserView extends ViewGroup implements ActivityChooserModelClient {
  
      /**
       * An adapter for displaying the activities in an {@link AdapterView}.
       */
      private final ActivityChooserViewAdapter mAdapter;
  
      /**
       * Implementation of various interfaces to avoid publishing them in the APIs.
       */
      private final Callbacks mCallbacks;
  
      /**
       * The content of this view.
       */
      private final IcsLinearLayout mActivityChooserContent;
  
      /**
       * Stores the background drawable to allow hiding and latter showing.
       */
      private final Drawable mActivityChooserContentBackground;
  
      /**
       * The expand activities action button;
       */
      private final FrameLayout mExpandActivityOverflowButton;
  
      /**
       * The image for the expand activities action button;
       */
      private final ImageView mExpandActivityOverflowButtonImage;
  
      /**
       * The default activities action button;
       */
      private final FrameLayout mDefaultActivityButton;
  
      /**
       * The image for the default activities action button;
       */
      private final ImageView mDefaultActivityButtonImage;
  
      /**
       * The maximal width of the list popup.
       */
      private final int mListPopupMaxWidth;
  
      /**
       * The ActionProvider hosting this view, if applicable.
       */
      ActionProvider mProvider;
  
      /**
       * Observer for the model data.
       */
      private final DataSetObserver mModelDataSetOberver = new DataSetObserver() {
  
          @Override
          public void onChanged() {
              super.onChanged();
              mAdapter.notifyDataSetChanged();
          }
          @Override
          public void onInvalidated() {
              super.onInvalidated();
              mAdapter.notifyDataSetInvalidated();
          }
      };
  
      private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() {
          @Override
          public void onGlobalLayout() {
              if (isShowingPopup()) {
                  if (!isShown()) {
                      getListPopupWindow().dismiss();
                  } else {
                      getListPopupWindow().show();
                      if (mProvider != null) {
                          mProvider.subUiVisibilityChanged(true);
                      }
                  }
              }
          }
      };
  
      /**
       * Popup window for showing the activity overflow list.
       */
      private IcsListPopupWindow mListPopupWindow;
  
      /**
       * Listener for the dismissal of the popup/alert.
       */
      private PopupWindow.OnDismissListener mOnDismissListener;
  
      /**
       * Flag whether a default activity currently being selected.
       */
      private boolean mIsSelectingDefaultActivity;
  
      /**
       * The count of activities in the popup.
       */
      private int mInitialActivityCount = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT;
  
      /**
       * Flag whether this view is attached to a window.
       */
      private boolean mIsAttachedToWindow;
  
      /**
       * String resource for formatting content description of the default target.
       */
      private int mDefaultActionButtonContentDescription;
  
      private final Context mContext;
  
      /**
       * Create a new instance.
       *
       * @param context The application environment.
       */
      public ActivityChooserView(Context context) {
          this(context, null);
      }
  
      /**
       * Create a new instance.
       *
       * @param context The application environment.
       * @param attrs A collection of attributes.
       */
      public ActivityChooserView(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      /**
       * Create a new instance.
       *
       * @param context The application environment.
       * @param attrs A collection of attributes.
       * @param defStyle The default style to apply to this view.
       */
      public ActivityChooserView(Context context, AttributeSet attrs, int defStyle) {
          super(context, attrs, defStyle);
          mContext = context;
  
          TypedArray attributesArray = context.obtainStyledAttributes(attrs,
                  R.styleable.SherlockActivityChooserView, defStyle, 0);
  
          mInitialActivityCount = attributesArray.getInt(
                  R.styleable.SherlockActivityChooserView_initialActivityCount,
                  ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT);
  
          Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable(
                  R.styleable.SherlockActivityChooserView_expandActivityOverflowButtonDrawable);
  
          attributesArray.recycle();
  
          LayoutInflater inflater = LayoutInflater.from(mContext);
          inflater.inflate(R.layout.abs__activity_chooser_view, this, true);
  
          mCallbacks = new Callbacks();
  
          mActivityChooserContent = (IcsLinearLayout) findViewById(R.id.abs__activity_chooser_view_content);
          mActivityChooserContentBackground = mActivityChooserContent.getBackground();
  
          mDefaultActivityButton = (FrameLayout) findViewById(R.id.abs__default_activity_button);
          mDefaultActivityButton.setOnClickListener(mCallbacks);
          mDefaultActivityButton.setOnLongClickListener(mCallbacks);
          mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.abs__image);
  
          mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.abs__expand_activities_button);
          mExpandActivityOverflowButton.setOnClickListener(mCallbacks);
          mExpandActivityOverflowButtonImage =
              (ImageView) mExpandActivityOverflowButton.findViewById(R.id.abs__image);
          mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
  
          mAdapter = new ActivityChooserViewAdapter();
          mAdapter.registerDataSetObserver(new DataSetObserver() {
              @Override
              public void onChanged() {
                  super.onChanged();
                  updateAppearance();
              }
          });
  
          Resources resources = context.getResources();
          mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
                resources.getDimensionPixelSize(R.dimen.abs__config_prefDialogWidth));
      }
  
      /**
       * {@inheritDoc}
       */
      public void setActivityChooserModel(ActivityChooserModel dataModel) {
          mAdapter.setDataModel(dataModel);
          if (isShowingPopup()) {
              dismissPopup();
              showPopup();
          }
      }
  
      /**
       * Sets the background for the button that expands the activity
       * overflow list.
       *
       * <strong>Note:</strong> Clients would like to set this drawable
       * as a clue about the action the chosen activity will perform. For
       * example, if a share activity is to be chosen the drawable should
       * give a clue that sharing is to be performed.
       *
       * @param drawable The drawable.
       */
      public void setExpandActivityOverflowButtonDrawable(Drawable drawable) {
          mExpandActivityOverflowButtonImage.setImageDrawable(drawable);
      }
  
      /**
       * Sets the content description for the button that expands the activity
       * overflow list.
       *
       * description as a clue about the action performed by the button.
       * For example, if a share activity is to be chosen the content
       * description should be something like "Share with".
       *
       * @param resourceId The content description resource id.
       */
      public void setExpandActivityOverflowButtonContentDescription(int resourceId) {
          CharSequence contentDescription = mContext.getString(resourceId);
          mExpandActivityOverflowButtonImage.setContentDescription(contentDescription);
      }
  
      /**
       * Set the provider hosting this view, if applicable.
       * @hide Internal use only
       */
      public void setProvider(ActionProvider provider) {
          mProvider = provider;
      }
  
      /**
       * Shows the popup window with activities.
       *
       * @return True if the popup was shown, false if already showing.
       */
      public boolean showPopup() {
          if (isShowingPopup() || !mIsAttachedToWindow) {
              return false;
          }
          mIsSelectingDefaultActivity = false;
          showPopupUnchecked(mInitialActivityCount);
          return true;
      }
  
      /**
       * Shows the popup no matter if it was already showing.
       *
       * @param maxActivityCount The max number of activities to display.
       */
      private void showPopupUnchecked(int maxActivityCount) {
          if (mAdapter.getDataModel() == null) {
              throw new IllegalStateException("No data model. Did you call #setDataModel?");
          }
  
          getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
  
          final boolean defaultActivityButtonShown =
              mDefaultActivityButton.getVisibility() == VISIBLE;
  
          final int activityCount = mAdapter.getActivityCount();
          final int maxActivityCountOffset = defaultActivityButtonShown ? 1 : 0;
          if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED
                  && activityCount > maxActivityCount + maxActivityCountOffset) {
              mAdapter.setShowFooterView(true);
              mAdapter.setMaxActivityCount(maxActivityCount - 1);
          } else {
              mAdapter.setShowFooterView(false);
              mAdapter.setMaxActivityCount(maxActivityCount);
          }
  
          IcsListPopupWindow popupWindow = getListPopupWindow();
          if (!popupWindow.isShowing()) {
              if (mIsSelectingDefaultActivity || !defaultActivityButtonShown) {
                  mAdapter.setShowDefaultActivity(true, defaultActivityButtonShown);
              } else {
                  mAdapter.setShowDefaultActivity(false, false);
              }
              final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth);
              popupWindow.setContentWidth(contentWidth);
              popupWindow.show();
              if (mProvider != null) {
                  mProvider.subUiVisibilityChanged(true);
              }
              popupWindow.getListView().setContentDescription(mContext.getString(
                      R.string.abs__activitychooserview_choose_application));
          }
      }
  
      /**
       * Dismisses the popup window with activities.
       *
       * @return True if dismissed, false if already dismissed.
       */
      public boolean dismissPopup() {
          if (isShowingPopup()) {
              getListPopupWindow().dismiss();
              ViewTreeObserver viewTreeObserver = getViewTreeObserver();
              if (viewTreeObserver.isAlive()) {
                  viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
              }
          }
          return true;
      }
  
      /**
       * Gets whether the popup window with activities is shown.
       *
       * @return True if the popup is shown.
       */
      public boolean isShowingPopup() {
          return getListPopupWindow().isShowing();
      }
  
      @Override
      protected void onAttachedToWindow() {
          super.onAttachedToWindow();
          ActivityChooserModel dataModel = mAdapter.getDataModel();
          if (dataModel != null) {
              try {
                  dataModel.registerObserver(mModelDataSetOberver);
              } catch (IllegalStateException e) {
                  // Related to #557.
              }
          }
          mIsAttachedToWindow = true;
      }
  
      @Override
      protected void onDetachedFromWindow() {
          super.onDetachedFromWindow();
          ActivityChooserModel dataModel = mAdapter.getDataModel();
          if (dataModel != null) {
              try {
                  dataModel.unregisterObserver(mModelDataSetOberver);
              } catch (IllegalStateException e) {
                  //Oh, well... fixes issue #557
              }
          }
          ViewTreeObserver viewTreeObserver = getViewTreeObserver();
          if (viewTreeObserver.isAlive()) {
              viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
          }
          mIsAttachedToWindow = false;
      }
  
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          View child = mActivityChooserContent;
          // If the default action is not visible we want to be as tall as the
          // ActionBar so if this widget is used in the latter it will look as
          // a normal action button.
          if (mDefaultActivityButton.getVisibility() != VISIBLE) {
              heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
                      MeasureSpec.EXACTLY);
          }
          measureChild(child, widthMeasureSpec, heightMeasureSpec);
          setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight());
      }
  
      @Override
      protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
          mActivityChooserContent.layout(0, 0, right - left, bottom - top);
          if (getListPopupWindow().isShowing()) {
              showPopupUnchecked(mAdapter.getMaxActivityCount());
          } else {
              dismissPopup();
          }
      }
  
      public ActivityChooserModel getDataModel() {
          return mAdapter.getDataModel();
      }
  
      /**
       * Sets a listener to receive a callback when the popup is dismissed.
       *
       * @param listener The listener to be notified.
       */
      public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
          mOnDismissListener = listener;
      }
  
      /**
       * Sets the initial count of items shown in the activities popup
       * i.e. the items before the popup is expanded. This is an upper
       * bound since it is not guaranteed that such number of intent
       * handlers exist.
       *
       * @param itemCount The initial popup item count.
       */
      public void setInitialActivityCount(int itemCount) {
          mInitialActivityCount = itemCount;
      }
  
      /**
       * Sets a content description of the default action button. This
       * resource should be a string taking one formatting argument and
       * will be used for formatting the content description of the button
       * dynamically as the default target changes. For example, a resource
       * pointing to the string "share with %1$s" will result in a content
       * description "share with Bluetooth" for the Bluetooth activity.
       *
       * @param resourceId The resource id.
       */
      public void setDefaultActionButtonContentDescription(int resourceId) {
          mDefaultActionButtonContentDescription = resourceId;
      }
  
      /**
       * Gets the list popup window which is lazily initialized.
       *
       * @return The popup.
       */
      private IcsListPopupWindow getListPopupWindow() {
          if (mListPopupWindow == null) {
              mListPopupWindow = new IcsListPopupWindow(getContext());
              mListPopupWindow.setAdapter(mAdapter);
              mListPopupWindow.setAnchorView(ActivityChooserView.this);
              mListPopupWindow.setModal(true);
              mListPopupWindow.setOnItemClickListener(mCallbacks);
              mListPopupWindow.setOnDismissListener(mCallbacks);
          }
          return mListPopupWindow;
      }
  
      /**
       * Updates the buttons state.
       */
      private void updateAppearance() {
          // Expand overflow button.
          if (mAdapter.getCount() > 0) {
              mExpandActivityOverflowButton.setEnabled(true);
          } else {
              mExpandActivityOverflowButton.setEnabled(false);
          }
          // Default activity button.
          final int activityCount = mAdapter.getActivityCount();
          final int historySize = mAdapter.getHistorySize();
          if (activityCount > 0 && historySize > 0) {
              mDefaultActivityButton.setVisibility(VISIBLE);
              ResolveInfo activity = mAdapter.getDefaultActivity();
              PackageManager packageManager = mContext.getPackageManager();
              mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager));
              if (mDefaultActionButtonContentDescription != 0) {
                  CharSequence label = activity.loadLabel(packageManager);
                  String contentDescription = mContext.getString(
                          mDefaultActionButtonContentDescription, label);
                  mDefaultActivityButton.setContentDescription(contentDescription);
              }
  
              // Work-around for #415.
              mAdapter.setShowDefaultActivity(false, false);
          } else {
              mDefaultActivityButton.setVisibility(View.GONE);
          }
          // Activity chooser content.
          if (mDefaultActivityButton.getVisibility() == VISIBLE) {
              mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground);
          } else {
              mActivityChooserContent.setBackgroundDrawable(null);
              mActivityChooserContent.setPadding(0, 0, 0, 0);
          }
      }
  
      /**
       * Interface implementation to avoid publishing them in the APIs.
       */
      private class Callbacks implements AdapterView.OnItemClickListener,
              View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener {
  
          // AdapterView#OnItemClickListener
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
              ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter();
              final int itemViewType = adapter.getItemViewType(position);
              switch (itemViewType) {
                  case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: {
                      showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED);
                  } break;
                  case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: {
                      dismissPopup();
                      if (mIsSelectingDefaultActivity) {
                          // The item at position zero is the default already.
                          if (position > 0) {
                              mAdapter.getDataModel().setDefaultActivity(position);
                          }
                      } else {
                          // If the default target is not shown in the list, the first
                          // item in the model is default action => adjust index
                          position = mAdapter.getShowDefaultActivity() ? position : position + 1;
                          Intent launchIntent = mAdapter.getDataModel().chooseActivity(position);
                          if (launchIntent != null) {
                              mContext.startActivity(launchIntent);
                          }
                      }
                  } break;
                  default:
                      throw new IllegalArgumentException();
              }
          }
  
          // View.OnClickListener
          public void onClick(View view) {
              if (view == mDefaultActivityButton) {
                  dismissPopup();
                  ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
                  final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
                  Intent launchIntent = mAdapter.getDataModel().chooseActivity(index);
                  if (launchIntent != null) {
                      mContext.startActivity(launchIntent);
                  }
              } else if (view == mExpandActivityOverflowButton) {
                  mIsSelectingDefaultActivity = false;
                  showPopupUnchecked(mInitialActivityCount);
              } else {
                  throw new IllegalArgumentException();
              }
          }
  
          // OnLongClickListener#onLongClick
          @Override
          public boolean onLongClick(View view) {
              if (view == mDefaultActivityButton) {
                  if (mAdapter.getCount() > 0) {
                      mIsSelectingDefaultActivity = true;
                      showPopupUnchecked(mInitialActivityCount);
                  }
              } else {
                  throw new IllegalArgumentException();
              }
              return true;
          }
  
          // PopUpWindow.OnDismissListener#onDismiss
          public void onDismiss() {
              notifyOnDismissListener();
              if (mProvider != null) {
                  mProvider.subUiVisibilityChanged(false);
              }
          }
  
          private void notifyOnDismissListener() {
              if (mOnDismissListener != null) {
                  mOnDismissListener.onDismiss();
              }
          }
      }
  
      private static class SetActivated {
          public static void invoke(View view, boolean activated) {
              view.setActivated(activated);
          }
      }
  
      private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
  
      /**
       * Adapter for backing the list of activities shown in the popup.
       */
      private class ActivityChooserViewAdapter extends BaseAdapter {
  
          public static final int MAX_ACTIVITY_COUNT_UNLIMITED = Integer.MAX_VALUE;
  
          public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4;
  
          private static final int ITEM_VIEW_TYPE_ACTIVITY = 0;
  
          private static final int ITEM_VIEW_TYPE_FOOTER = 1;
  
          private static final int ITEM_VIEW_TYPE_COUNT = 3;
  
          private ActivityChooserModel mDataModel;
  
          private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT;
  
          // Work-around for #415.
          private boolean mShowDefaultActivity = true;
  
          private boolean mHighlightDefaultActivity;
  
          private boolean mShowFooterView;
  
          public void setDataModel(ActivityChooserModel dataModel) {
              ActivityChooserModel oldDataModel = mAdapter.getDataModel();
              if (oldDataModel != null && isShown()) {
                  try {
                      oldDataModel.unregisterObserver(mModelDataSetOberver);
                  } catch (IllegalStateException e) {
                      //Oh, well... fixes issue #557
                  }
              }
              mDataModel = dataModel;
              if (dataModel != null && isShown()) {
                  try {
                      dataModel.registerObserver(mModelDataSetOberver);
                  } catch (IllegalStateException e) {
                      // Related to #557.
                  }
              }
              notifyDataSetChanged();
          }
  
          @Override
          public int getItemViewType(int position) {
              if (mShowFooterView && position == getCount() - 1) {
                  return ITEM_VIEW_TYPE_FOOTER;
              } else {
                  return ITEM_VIEW_TYPE_ACTIVITY;
              }
          }
  
          @Override
          public int getViewTypeCount() {
              return ITEM_VIEW_TYPE_COUNT;
          }
  
          public int getCount() {
              int count = 0;
              int activityCount = mDataModel.getActivityCount();
              if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
                  activityCount--;
              }
              count = Math.min(activityCount, mMaxActivityCount);
              if (mShowFooterView) {
                  count++;
              }
              return count;
          }
  
          public Object getItem(int position) {
              final int itemViewType = getItemViewType(position);
              switch (itemViewType) {
                  case ITEM_VIEW_TYPE_FOOTER:
                      return null;
                  case ITEM_VIEW_TYPE_ACTIVITY:
                      if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
                          position++;
                      }
                      return mDataModel.getActivity(position);
                  default:
                      throw new IllegalArgumentException();
              }
          }
  
          public long getItemId(int position) {
              return position;
          }
  
          public View getView(int position, View convertView, ViewGroup parent) {
              final int itemViewType = getItemViewType(position);
              switch (itemViewType) {
                  case ITEM_VIEW_TYPE_FOOTER:
                      if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) {
                          convertView = LayoutInflater.from(getContext()).inflate(
                                  R.layout.abs__activity_chooser_view_list_item, parent, false);
                          convertView.setId(ITEM_VIEW_TYPE_FOOTER);
                          TextView titleView = (TextView) convertView.findViewById(R.id.abs__title);
                          titleView.setText(mContext.getString(
                                  R.string.abs__activity_chooser_view_see_all));
                      }
                      return convertView;
                  case ITEM_VIEW_TYPE_ACTIVITY:
                      if (convertView == null || convertView.getId() != R.id.abs__list_item) {
                          convertView = LayoutInflater.from(getContext()).inflate(
                                  R.layout.abs__activity_chooser_view_list_item, parent, false);
                      }
                      PackageManager packageManager = mContext.getPackageManager();
                      // Set the icon
                      ImageView iconView = (ImageView) convertView.findViewById(R.id.abs__icon);
                      ResolveInfo activity = (ResolveInfo) getItem(position);
                      iconView.setImageDrawable(activity.loadIcon(packageManager));
                      // Set the title.
                      TextView titleView = (TextView) convertView.findViewById(R.id.abs__title);
                      titleView.setText(activity.loadLabel(packageManager));
                      if (IS_HONEYCOMB) {
                          // Highlight the default.
                          if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
                              SetActivated.invoke(convertView, true);
                          } else {
                              SetActivated.invoke(convertView, false);
                          }
                      }
                      return convertView;
                  default:
                      throw new IllegalArgumentException();
              }
          }
  
          public int measureContentWidth() {
              // The user may have specified some of the target not to be shown but we
              // want to measure all of them since after expansion they should fit.
              final int oldMaxActivityCount = mMaxActivityCount;
              mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED;
  
              int contentWidth = 0;
              View itemView = null;
  
              final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
              final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
              final int count = getCount();
  
              for (int i = 0; i < count; i++) {
                  itemView = getView(i, itemView, null);
                  itemView.measure(widthMeasureSpec, heightMeasureSpec);
                  contentWidth = Math.max(contentWidth, itemView.getMeasuredWidth());
              }
  
              mMaxActivityCount = oldMaxActivityCount;
  
              return contentWidth;
          }
  
          public void setMaxActivityCount(int maxActivityCount) {
              if (mMaxActivityCount != maxActivityCount) {
                  mMaxActivityCount = maxActivityCount;
                  notifyDataSetChanged();
              }
          }
  
          public ResolveInfo getDefaultActivity() {
              return mDataModel.getDefaultActivity();
          }
  
          public void setShowFooterView(boolean showFooterView) {
              if (mShowFooterView != showFooterView) {
                  mShowFooterView = showFooterView;
                  notifyDataSetChanged();
              }
          }
  
          public int getActivityCount() {
              return mDataModel.getActivityCount();
          }
  
          public int getHistorySize() {
              return mDataModel.getHistorySize();
          }
  
          public int getMaxActivityCount() {
              return mMaxActivityCount;
          }
  
          public ActivityChooserModel getDataModel() {
              return mDataModel;
          }
  
          public void setShowDefaultActivity(boolean showDefaultActivity,
                  boolean highlightDefaultActivity) {
              if (mShowDefaultActivity != showDefaultActivity
                      || mHighlightDefaultActivity != highlightDefaultActivity) {
                  mShowDefaultActivity = showDefaultActivity;
                  mHighlightDefaultActivity = highlightDefaultActivity;
                  notifyDataSetChanged();
              }
          }
  
          public boolean getShowDefaultActivity() {
              return mShowDefaultActivity;
          }
      }
  }
  