ActivityChooserView.java revision 823f074a73cfc23c40a7b576c71daa096ee9ed6a
151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov/*
251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Copyright (C) 2011 The Android Open Source Project
351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License");
551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * you may not use this file except in compliance with the License.
651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * You may obtain a copy of the License at
751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *      http://www.apache.org/licenses/LICENSE-2.0
951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
1051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software
1151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS,
1251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * See the License for the specific language governing permissions and
1451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * limitations under the License.
1551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */
1651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
1751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovpackage android.widget;
1851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
19823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powellimport com.android.internal.R;
20823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell
2151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.Context;
2251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.Intent;
2351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.pm.PackageManager;
2451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.pm.ResolveInfo;
25414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganovimport android.content.res.Resources;
2651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.res.TypedArray;
2751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.database.DataSetObserver;
2851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.graphics.drawable.Drawable;
2951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.util.AttributeSet;
30823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powellimport android.view.ActionProvider;
3151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.LayoutInflater;
3251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.View;
3351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.ViewGroup;
348c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganovimport android.view.ViewTreeObserver;
358c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganovimport android.view.ViewTreeObserver.OnGlobalLayoutListener;
3651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.widget.ActivityChooserModel.ActivityChooserModelClient;
3751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
3851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov/**
3951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * This class is a view for choosing an activity for handling a given {@link Intent}.
4051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <p>
4151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The view is composed of two adjacent buttons:
4251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <ul>
4351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <li>
4451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The left button is an immediate action and allows one click activity choosing.
4551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Tapping this button immediately executes the intent without requiring any further
4651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * user input. Long press on this button shows a popup for changing the default
4751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * activity.
4851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </li>
4951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <li>
5051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The right button is an overflow action and provides an optimized menu
5151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * of additional activities. Tapping this button shows a popup anchored to this
5251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * view, listing the most frequently used activities. This list is initially
5351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * limited to a small number of items in frequency used order. The last item,
5451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * "Show all..." serves as an affordance to display all available activities.
5551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </li>
5651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </ul>
5751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </p>
5851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov *
5951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @hide
6051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */
6151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovpublic class ActivityChooserView extends ViewGroup implements ActivityChooserModelClient {
6251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
6351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
6451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * An adapter for displaying the activities in an {@link AdapterView}.
6551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
6651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private final ActivityChooserViewAdapter mAdapter;
6751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
6851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
6951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Implementation of various interfaces to avoid publishing them in the APIs.
7051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
7151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private final Callbacks mCallbacks;
7251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
7351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
7451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * The content of this view.
7551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
7651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private final LinearLayout mActivityChooserContent;
7751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
7851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
79f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov     * Stores the background drawable to allow hiding and latter showing.
80f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov     */
81f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov    private final Drawable mActivityChooserContentBackground;
82f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov
83f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov    /**
8451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * The expand activities action button;
8551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
86bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov    private final FrameLayout mExpandActivityOverflowButton;
87bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov
88bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov    /**
89bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov     * The image for the expand activities action button;
90bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov     */
91bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov    private final ImageView mExpandActivityOverflowButtonImage;
9251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
9351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
9451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * The default activities action button;
9551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
96bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov    private final FrameLayout mDefaultActivityButton;
97bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov
98bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov    /**
99bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov     * The image for the default activities action button;
100bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov     */
101bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov    private final ImageView mDefaultActivityButtonImage;
10251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
10351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
104414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov     * The maximal width of the list popup.
105414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov     */
106414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov    private final int mListPopupMaxWidth;
107414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov
108414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov    /**
109823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell     * The ActionProvider hosting this view, if applicable.
110823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell     */
111823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell    ActionProvider mProvider;
112823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell
113823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell    /**
11476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov     * Observer for the model data.
11551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
11676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    private final DataSetObserver mModelDataSetOberver = new DataSetObserver() {
11751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
11876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        @Override
11976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        public void onChanged() {
12076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            super.onChanged();
12176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            mAdapter.notifyDataSetChanged();
12276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        }
12376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        @Override
12476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        public void onInvalidated() {
12576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            super.onInvalidated();
12676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            mAdapter.notifyDataSetInvalidated();
12776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        }
12876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov    };
12951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
1308c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() {
1318c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        @Override
1328c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        public void onGlobalLayout() {
1338c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            if (isShowingPopup()) {
1348c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                if (!isShown()) {
1358c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                    getListPopupWindow().dismiss();
1368c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                } else {
1378c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                    getListPopupWindow().show();
138823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                    if (mProvider != null) {
139823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                        mProvider.subUiVisibilityChanged(true);
140823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                    }
1418c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                }
1428c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            }
1438c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        }
1448c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov    };
1458c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
14651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
14751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Popup window for showing the activity overflow list.
14851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
14951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private ListPopupWindow mListPopupWindow;
15051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
15151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
15251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Listener for the dismissal of the popup/alert.
15351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
15451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private PopupWindow.OnDismissListener mOnDismissListener;
15551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
15651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
15751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Flag whether a default activity currently being selected.
15851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
15951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private boolean mIsSelectingDefaultActivity;
16051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
16151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
16251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * The count of activities in the popup.
16351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
16451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private int mInitialActivityCount = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT;
16551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
16651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
16751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Flag whether this view is attached to a window.
16851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
16951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private boolean mIsAttachedToWindow;
17051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
17151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
17251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Create a new instance.
17351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
17451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param context The application environment.
17551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
17651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public ActivityChooserView(Context context) {
17751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        this(context, null);
17851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
17951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
18051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
18151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Create a new instance.
18251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
18351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param context The application environment.
18451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param attrs A collection of attributes.
18551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
18651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public ActivityChooserView(Context context, AttributeSet attrs) {
18723f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell        this(context, attrs, 0);
18851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
18951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
19051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
19151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Create a new instance.
19251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
19351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param context The application environment.
19451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param attrs A collection of attributes.
19551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param defStyle The default style to apply to this view.
19651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
19751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public ActivityChooserView(Context context, AttributeSet attrs, int defStyle) {
19851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        super(context, attrs, defStyle);
19951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
20051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        TypedArray attributesArray = context.obtainStyledAttributes(attrs,
20151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                R.styleable.ActivityChooserView, defStyle, 0);
20251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
20351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mInitialActivityCount = attributesArray.getInt(
20451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                R.styleable.ActivityChooserView_initialActivityCount,
20551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT);
20651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
20751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable(
20851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                R.styleable.ActivityChooserView_expandActivityOverflowButtonDrawable);
20951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
210f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        attributesArray.recycle();
211f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov
21276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        LayoutInflater inflater = LayoutInflater.from(mContext);
21351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        inflater.inflate(R.layout.activity_chooser_view, this, true);
21451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
21551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mCallbacks = new Callbacks();
21651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
21751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mActivityChooserContent = (LinearLayout) findViewById(R.id.activity_chooser_view_content);
218f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        mActivityChooserContentBackground = mActivityChooserContent.getBackground();
21951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
220bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov        mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
221bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov        mDefaultActivityButton.setOnClickListener(mCallbacks);
222bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov        mDefaultActivityButton.setOnLongClickListener(mCallbacks);
223bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov        mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
22451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
225bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov        mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.expand_activities_button);
22651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mExpandActivityOverflowButton.setOnClickListener(mCallbacks);
227bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov        mExpandActivityOverflowButtonImage =
228bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov            (ImageView) mExpandActivityOverflowButton.findViewById(R.id.image);
229bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov        mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
23051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
23151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mAdapter = new ActivityChooserViewAdapter();
23251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mAdapter.registerDataSetObserver(new DataSetObserver() {
23351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            @Override
23451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            public void onChanged() {
23551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                super.onChanged();
236f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov                updateAppearance();
23751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
23851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        });
239414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov
240414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov        Resources resources = context.getResources();
241414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov        mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
242414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov              resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
24351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
24451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
24551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
24651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * {@inheritDoc}
24751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
24851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public void setActivityChooserModel(ActivityChooserModel dataModel) {
24951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mAdapter.setDataModel(dataModel);
25051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        if (isShowingPopup()) {
25151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            dismissPopup();
25251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            showPopup();
25351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
25451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
25551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
25651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
25751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Sets the background for the button that expands the activity
25851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * overflow list.
25951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
26051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * <strong>Note:</strong> Clients would like to set this drawable
26151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * as a clue about the action the chosen activity will perform. For
26251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * example, if share activity is to be chosen the drawable should
26351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * give a clue that sharing is to be performed.
26451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
26551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param drawable The drawable.
26651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
26751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public void setExpandActivityOverflowButtonDrawable(Drawable drawable) {
268bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov        mExpandActivityOverflowButtonImage.setImageDrawable(drawable);
26951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
27051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
27151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
272823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell     * Set the provider hosting this view, if applicable.
273823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell     * @hide Internal use only
274823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell     */
275823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell    public void setProvider(ActionProvider provider) {
276823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell        mProvider = provider;
277823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell    }
278823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell
279823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell    /**
28051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Shows the popup window with activities.
28151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
28251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @return True if the popup was shown, false if already showing.
28351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
28451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public boolean showPopup() {
28576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        if (isShowingPopup() || !mIsAttachedToWindow) {
28651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return false;
28751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
28851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mIsSelectingDefaultActivity = false;
28951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        showPopupUnchecked(mInitialActivityCount);
29051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        return true;
29151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
29251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
29351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
29451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Shows the popup no matter if it was already showing.
29551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
29651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param maxActivityCount The max number of activities to display.
29751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
29851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private void showPopupUnchecked(int maxActivityCount) {
29976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        if (mAdapter.getDataModel() == null) {
30076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            throw new IllegalStateException("No data model. Did you call #setDataModel?");
30151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
30251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
3038c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
3048c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov
30576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        mAdapter.setMaxActivityCount(maxActivityCount);
30676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
30776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        final int activityCount = mAdapter.getActivityCount();
30876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED
30976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                && activityCount > maxActivityCount + 1) {
31076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            mAdapter.setShowFooterView(true);
31151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        } else {
31276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            mAdapter.setShowFooterView(false);
31351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
31451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
31576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        ListPopupWindow popupWindow = getListPopupWindow();
31676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        if (!popupWindow.isShowing()) {
317efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov            final boolean defaultActivityButtonShown =
318efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                mDefaultActivityButton.getVisibility() == VISIBLE;
319efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov            if (mIsSelectingDefaultActivity || !defaultActivityButtonShown) {
320efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                mAdapter.setShowDefaultActivity(true, defaultActivityButtonShown);
32176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            } else {
322efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                mAdapter.setShowDefaultActivity(false, false);
32351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
324414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov            final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth);
325414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov            popupWindow.setContentWidth(contentWidth);
32676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            popupWindow.show();
327823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            if (mProvider != null) {
328823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                mProvider.subUiVisibilityChanged(true);
329823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            }
33051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
33151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
33251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
33351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
33451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Dismisses the popup window with activities.
33551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
33651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @return True if dismissed, false if already dismissed.
33751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
33851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public boolean dismissPopup() {
33976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        if (isShowingPopup()) {
34051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            getListPopupWindow().dismiss();
3418c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            ViewTreeObserver viewTreeObserver = getViewTreeObserver();
3428c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            if (viewTreeObserver.isAlive()) {
3438c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
3448c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            }
34551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
34651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        return true;
34751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
34851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
34951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
35051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Gets whether the popup window with activities is shown.
35151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
35251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @return True if the popup is shown.
35351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
35451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public boolean isShowingPopup() {
35576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        return getListPopupWindow().isShowing();
35651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
35751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
35851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    @Override
35951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    protected void onAttachedToWindow() {
36051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        super.onAttachedToWindow();
36151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        ActivityChooserModel dataModel = mAdapter.getDataModel();
36251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        if (dataModel != null) {
36376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            dataModel.registerObserver(mModelDataSetOberver);
36451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
36551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mIsAttachedToWindow = true;
36651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
36751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
36851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    @Override
36951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    protected void onDetachedFromWindow() {
37051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        super.onDetachedFromWindow();
37151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        ActivityChooserModel dataModel = mAdapter.getDataModel();
37251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        if (dataModel != null) {
37376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            dataModel.unregisterObserver(mModelDataSetOberver);
37451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
3758c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        ViewTreeObserver viewTreeObserver = getViewTreeObserver();
3768c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        if (viewTreeObserver.isAlive()) {
3778c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov            viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
3788c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov        }
37951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mIsAttachedToWindow = false;
38051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
38151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
38251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    @Override
38351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
384f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        View child = mActivityChooserContent;
385f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        // If the default action is not visible we want to be as tall as the
386f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        // ActionBar so if this widget is used in the latter it will look as
387f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        // a normal action button.
388f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        if (mDefaultActivityButton.getVisibility() != VISIBLE) {
389f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov            heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
390f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov                    MeasureSpec.EXACTLY);
391f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        }
392f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        measureChild(child, widthMeasureSpec, heightMeasureSpec);
393f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight());
39451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
39551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
39651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    @Override
39751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
39876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        mActivityChooserContent.layout(0, 0, right - left, bottom - top);
39976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        if (getListPopupWindow().isShowing()) {
40076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            showPopupUnchecked(mAdapter.getMaxActivityCount());
40176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        } else {
40276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            dismissPopup();
40351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
40451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
40551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
40651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public ActivityChooserModel getDataModel() {
40751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        return mAdapter.getDataModel();
40851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
40951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
41051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
41151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Sets a listener to receive a callback when the popup is dismissed.
41251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
41351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param listener The listener to be notified.
41451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
41551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
41651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mOnDismissListener = listener;
41751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
41851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
41951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
42051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Sets the initial count of items shown in the activities popup
42151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * i.e. the items before the popup is expanded. This is an upper
42251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * bound since it is not guaranteed that such number of intent
42351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * handlers exist.
42451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
42551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @param itemCount The initial popup item count.
42651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
42751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    public void setInitialActivityCount(int itemCount) {
42851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        mInitialActivityCount = itemCount;
42951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
43051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
43151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
43251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Gets the list popup window which is lazily initialized.
43351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     *
43451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * @return The popup.
43551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
43651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private ListPopupWindow getListPopupWindow() {
43751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        if (mListPopupWindow == null) {
43851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mListPopupWindow = new ListPopupWindow(getContext());
43951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mListPopupWindow.setAdapter(mAdapter);
44051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mListPopupWindow.setAnchorView(ActivityChooserView.this);
44151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mListPopupWindow.setModal(true);
44251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mListPopupWindow.setOnItemClickListener(mCallbacks);
44351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mListPopupWindow.setOnDismissListener(mCallbacks);
44451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
44551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        return mListPopupWindow;
44651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
44751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
44851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
44951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Updates the buttons state.
45051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
451f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov    private void updateAppearance() {
452f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        // Expand overflow button.
453f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        if (mAdapter.getCount() > 0) {
454f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov            mExpandActivityOverflowButton.setEnabled(true);
455f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        } else {
456f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov            mExpandActivityOverflowButton.setEnabled(false);
457f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        }
458f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        // Default activity button.
45951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        final int activityCount = mAdapter.getActivityCount();
460f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        final int historySize = mAdapter.getHistorySize();
461f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        if (activityCount > 0 && historySize > 0) {
462bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov            mDefaultActivityButton.setVisibility(VISIBLE);
46351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            ResolveInfo activity = mAdapter.getDefaultActivity();
46451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            PackageManager packageManager = mContext.getPackageManager();
465bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov            mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager));
46651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        } else {
467f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov            mDefaultActivityButton.setVisibility(View.GONE);
468f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        }
469f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        // Activity chooser content.
470f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        if (mDefaultActivityButton.getVisibility() == VISIBLE) {
471f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov            mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground);
472f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        } else {
473f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov            mActivityChooserContent.setBackgroundDrawable(null);
47451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
47551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
47651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
47751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
47851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Interface implementation to avoid publishing them in the APIs.
47951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
48051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private class Callbacks implements AdapterView.OnItemClickListener,
48176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener {
48251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
48351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        // AdapterView#OnItemClickListener
48451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
48551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter();
48651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            final int itemViewType = adapter.getItemViewType(position);
48751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            switch (itemViewType) {
48851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: {
48951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED);
49051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                } break;
49151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: {
49251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    dismissPopup();
49351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    if (mIsSelectingDefaultActivity) {
49476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        // The item at position zero is the default already.
49576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        if (position > 0) {
49676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                            mAdapter.getDataModel().setDefaultActivity(position);
49776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        }
49851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    } else {
499efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                        // If the default target is not shown in the list, the first
500efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                        // item in the model is default action => adjust index
501efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                        position = mAdapter.getShowDefaultActivity() ? position : position + 1;
502efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                        Intent launchIntent = mAdapter.getDataModel().chooseActivity(position);
5038c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                        if (launchIntent != null) {
5048c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                            mContext.startActivity(launchIntent);
5058c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                        }
50651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    }
50751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                } break;
50851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                default:
50951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    throw new IllegalArgumentException();
51051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
51151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
51251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
51351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        // View.OnClickListener
51451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public void onClick(View view) {
515bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov            if (view == mDefaultActivityButton) {
51651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                dismissPopup();
51751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
51851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
51951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                Intent launchIntent = mAdapter.getDataModel().chooseActivity(index);
5208c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                if (launchIntent != null) {
5218c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                    mContext.startActivity(launchIntent);
5228c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov                }
52351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            } else if (view == mExpandActivityOverflowButton) {
52451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                mIsSelectingDefaultActivity = false;
52551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                showPopupUnchecked(mInitialActivityCount);
52651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            } else {
52751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                throw new IllegalArgumentException();
52851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
52951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
53051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
53151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        // OnLongClickListener#onLongClick
53251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        @Override
53351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public boolean onLongClick(View view) {
534bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov            if (view == mDefaultActivityButton) {
53551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                if (mAdapter.getCount() > 0) {
53651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    mIsSelectingDefaultActivity = true;
53751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    showPopupUnchecked(mInitialActivityCount);
53851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                }
53951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            } else {
54051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                throw new IllegalArgumentException();
54151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
54251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return true;
54351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
54451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
54551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        // PopUpWindow.OnDismissListener#onDismiss
54651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public void onDismiss() {
54751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            notifyOnDismissListener();
548823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            if (mProvider != null) {
549823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell                mProvider.subUiVisibilityChanged(false);
550823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell            }
55151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
55251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
55351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        private void notifyOnDismissListener() {
55451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            if (mOnDismissListener != null) {
55551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                mOnDismissListener.onDismiss();
55651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
55751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
55851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
55951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
56051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    /**
56151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     * Adapter for backing the list of activities shown in the popup.
56251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov     */
56351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    private class ActivityChooserViewAdapter extends BaseAdapter {
56451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
56551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public static final int MAX_ACTIVITY_COUNT_UNLIMITED = Integer.MAX_VALUE;
56651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
56751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4;
56851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
56976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        private static final int ITEM_VIEW_TYPE_ACTIVITY = 0;
57051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
57176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        private static final int ITEM_VIEW_TYPE_FOOTER = 1;
57251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
57351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        private static final int ITEM_VIEW_TYPE_COUNT = 3;
57451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
57551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        private ActivityChooserModel mDataModel;
57651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
57751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT;
57851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
57976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        private boolean mShowDefaultActivity;
58051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
581efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov        private boolean mHighlightDefaultActivity;
582efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov
58376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        private boolean mShowFooterView;
58451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
58551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public void setDataModel(ActivityChooserModel dataModel) {
58676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            ActivityChooserModel oldDataModel = mAdapter.getDataModel();
58776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            if (oldDataModel != null && isShown()) {
58876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                oldDataModel.unregisterObserver(mModelDataSetOberver);
58976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            }
59051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mDataModel = dataModel;
59176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            if (dataModel != null && isShown()) {
59276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                dataModel.registerObserver(mModelDataSetOberver);
59351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
59476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            notifyDataSetChanged();
59551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
59651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
59751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        @Override
59851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public int getItemViewType(int position) {
59976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            if (mShowFooterView && position == getCount() - 1) {
60051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                return ITEM_VIEW_TYPE_FOOTER;
60151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            } else {
60251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                return ITEM_VIEW_TYPE_ACTIVITY;
60351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
60451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
60551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
60651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        @Override
60751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public int getViewTypeCount() {
60851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return ITEM_VIEW_TYPE_COUNT;
60951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
61051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
61151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public int getCount() {
61251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            int count = 0;
61351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            int activityCount = mDataModel.getActivityCount();
61476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
61551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                activityCount--;
61651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
61751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            count = Math.min(activityCount, mMaxActivityCount);
61876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            if (mShowFooterView) {
61951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                count++;
62051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
62151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return count;
62251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
62351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
62451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public Object getItem(int position) {
62551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            final int itemViewType = getItemViewType(position);
62651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            switch (itemViewType) {
62751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                case ITEM_VIEW_TYPE_FOOTER:
62876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    return null;
62951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                case ITEM_VIEW_TYPE_ACTIVITY:
63076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
63176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        position++;
63251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    }
63376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    return mDataModel.getActivity(position);
63451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                default:
63551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    throw new IllegalArgumentException();
63651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
63751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
63851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
63951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public long getItemId(int position) {
64051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return position;
64151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
64251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
64351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public View getView(int position, View convertView, ViewGroup parent) {
64451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            final int itemViewType = getItemViewType(position);
64551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            switch (itemViewType) {
64651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                case ITEM_VIEW_TYPE_FOOTER:
64776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) {
64876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        convertView = LayoutInflater.from(getContext()).inflate(
64976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                                R.layout.activity_chooser_view_list_item, parent, false);
65076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        convertView.setId(ITEM_VIEW_TYPE_FOOTER);
65176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        TextView titleView = (TextView) convertView.findViewById(R.id.title);
65276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        titleView.setText(mContext.getString(
65376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                                R.string.activity_chooser_view_see_all));
65476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    }
65576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    return convertView;
65651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                case ITEM_VIEW_TYPE_ACTIVITY:
65751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    if (convertView == null || convertView.getId() != R.id.list_item) {
65851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                        convertView = LayoutInflater.from(getContext()).inflate(
65951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                                R.layout.activity_chooser_view_list_item, parent, false);
66051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    }
66151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    PackageManager packageManager = mContext.getPackageManager();
66251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    // Set the icon
66351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
66451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    ResolveInfo activity = (ResolveInfo) getItem(position);
665414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov                    iconView.setImageDrawable(activity.loadIcon(packageManager));
66651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    // Set the title.
66751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    TextView titleView = (TextView) convertView.findViewById(R.id.title);
66851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    titleView.setText(activity.loadLabel(packageManager));
66976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    // Highlight the default.
670efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                    if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
67176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        convertView.setActivated(true);
67276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    } else {
67376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                        convertView.setActivated(false);
67476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                    }
67551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    return convertView;
67651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                default:
67751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                    throw new IllegalArgumentException();
67851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
67951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
68051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
68151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public int measureContentWidth() {
68276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            // The user may have specified some of the target not to be shown but we
68351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            // want to measure all of them since after expansion they should fit.
68451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            final int oldMaxActivityCount = mMaxActivityCount;
68551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED;
68651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
68751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            int contentWidth = 0;
68851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            View itemView = null;
68951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
69051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
69151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
69251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            final int count = getCount();
69351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
69451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            for (int i = 0; i < count; i++) {
69551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                itemView = getView(i, itemView, null);
69651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                itemView.measure(widthMeasureSpec, heightMeasureSpec);
69751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                contentWidth = Math.max(contentWidth, itemView.getMeasuredWidth());
69851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
69951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
70051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            mMaxActivityCount = oldMaxActivityCount;
70151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
70251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return contentWidth;
70351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
70451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
70551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public void setMaxActivityCount(int maxActivityCount) {
70651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            if (mMaxActivityCount != maxActivityCount) {
70751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                mMaxActivityCount = maxActivityCount;
70851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                notifyDataSetChanged();
70951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
71051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
71151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
71251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public ResolveInfo getDefaultActivity() {
71376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            return mDataModel.getDefaultActivity();
71451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
71551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
71676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        public void setShowFooterView(boolean showFooterView) {
71776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            if (mShowFooterView != showFooterView) {
71876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                mShowFooterView = showFooterView;
71951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov                notifyDataSetChanged();
72051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            }
72151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
72251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
72351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public int getActivityCount() {
72451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return mDataModel.getActivityCount();
72551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
72651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
727f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        public int getHistorySize() {
728f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov            return mDataModel.getHistorySize();
729f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov        }
730f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov
73151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public int getMaxActivityCount() {
73251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return mMaxActivityCount;
73351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
73451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov
73551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        public ActivityChooserModel getDataModel() {
73651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov            return mDataModel;
73751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov        }
73876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov
739efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov        public void setShowDefaultActivity(boolean showDefaultActivity,
740efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                boolean highlightDefaultActivity) {
741efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov            if (mShowDefaultActivity != showDefaultActivity
742efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                    || mHighlightDefaultActivity != highlightDefaultActivity) {
74376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                mShowDefaultActivity = showDefaultActivity;
744efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov                mHighlightDefaultActivity = highlightDefaultActivity;
74576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov                notifyDataSetChanged();
74676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov            }
74776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov        }
748efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov
749efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov        public boolean getShowDefaultActivity() {
750efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov            return mShowDefaultActivity;
751efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov        }
75251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov    }
75351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov}
754