blob: 9a1e38dca230d143c7062c4a512c7565d28d524a [file] [log] [blame]
Jim Miller44c66fe2010-10-20 18:32:52 -07001/*
Jim Miller9f0f0e02011-05-17 20:06:29 -07002 * Copyright (C) 2011 The Android Open Source Project
Jim Miller44c66fe2010-10-20 18:32:52 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jim Miller9f0f0e02011-05-17 20:06:29 -070017package com.android.systemui.recent;
Jim Miller44c66fe2010-10-20 18:32:52 -070018
Michael Jurka3b1fc472011-06-13 10:54:40 -070019import android.animation.Animator;
Jim Miller9f0f0e02011-05-17 20:06:29 -070020import android.animation.LayoutTransition;
Michael Jurka9bdaada2012-10-01 13:58:29 +020021import android.animation.TimeInterpolator;
Jim Miller44c66fe2010-10-20 18:32:52 -070022import android.app.ActivityManager;
Michael Jurka56a57832012-05-14 13:24:43 -070023import android.app.ActivityManagerNative;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070024import android.app.ActivityOptions;
Adam Powell0fc5b2b2012-07-18 18:20:29 -070025import android.app.TaskStackBuilder;
Jim Miller44c66fe2010-10-20 18:32:52 -070026import android.content.Context;
27import android.content.Intent;
Michael Jurka9bdaada2012-10-01 13:58:29 +020028import android.content.res.Configuration;
Michael Jurkabfd24ac2011-11-13 13:50:38 -080029import android.content.res.Resources;
Daniel Sandler4a066c52012-04-20 14:49:13 -040030import android.content.res.TypedArray;
Jim Miller44c66fe2010-10-20 18:32:52 -070031import android.graphics.Bitmap;
Jim Millerfefef312010-11-09 14:08:39 -080032import android.graphics.Matrix;
Jim Millere5c16ab2010-12-03 19:18:38 -080033import android.graphics.Shader.TileMode;
34import android.graphics.drawable.BitmapDrawable;
Michael Jurka99a96552012-01-27 17:23:38 -080035import android.graphics.drawable.Drawable;
Jim Millerc0d27312011-07-14 18:54:01 -070036import android.net.Uri;
Michael Jurka482f1592012-09-13 11:05:59 -070037import android.os.Bundle;
Michael Jurka56a57832012-05-14 13:24:43 -070038import android.os.RemoteException;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070039import android.os.UserHandle;
Jim Millerc0d27312011-07-14 18:54:01 -070040import android.provider.Settings;
Jim Miller44c66fe2010-10-20 18:32:52 -070041import android.util.AttributeSet;
42import android.util.Log;
Jim Miller5fda69c2011-02-16 15:17:11 -080043import android.view.LayoutInflater;
Jim Millerc0d27312011-07-14 18:54:01 -070044import android.view.MenuItem;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070045import android.view.MotionEvent;
Jim Miller44c66fe2010-10-20 18:32:52 -070046import android.view.View;
Jim Miller5fda69c2011-02-16 15:17:11 -080047import android.view.ViewGroup;
Jim Miller17377762011-10-11 15:33:34 -070048import android.view.accessibility.AccessibilityEvent;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -070049import android.view.animation.AnimationUtils;
Michael Jurka9bdaada2012-10-01 13:58:29 +020050import android.view.animation.DecelerateInterpolator;
Jim Miller5fda69c2011-02-16 15:17:11 -080051import android.widget.AdapterView;
Michael Jurkabfd24ac2011-11-13 13:50:38 -080052import android.widget.AdapterView.OnItemClickListener;
Jim Miller5fda69c2011-02-16 15:17:11 -080053import android.widget.BaseAdapter;
Michael Jurka99a96552012-01-27 17:23:38 -080054import android.widget.FrameLayout;
Jim Miller44c66fe2010-10-20 18:32:52 -070055import android.widget.ImageView;
Michael Jurkabfd24ac2011-11-13 13:50:38 -080056import android.widget.ImageView.ScaleType;
Jim Millerc0d27312011-07-14 18:54:01 -070057import android.widget.PopupMenu;
Jim Miller44c66fe2010-10-20 18:32:52 -070058import android.widget.TextView;
Jim Miller44c66fe2010-10-20 18:32:52 -070059
60import com.android.systemui.R;
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -050061import com.android.systemui.statusbar.BaseStatusBar;
Michael Jurka3b1fc472011-06-13 10:54:40 -070062import com.android.systemui.statusbar.phone.PhoneStatusBar;
Jim Miller9f0f0e02011-05-17 20:06:29 -070063import com.android.systemui.statusbar.tablet.StatusBarPanel;
64import com.android.systemui.statusbar.tablet.TabletStatusBar;
Jim Miller44c66fe2010-10-20 18:32:52 -070065
Michael Jurkabfd24ac2011-11-13 13:50:38 -080066import java.util.ArrayList;
67
Michael Jurka99a96552012-01-27 17:23:38 -080068public class RecentsPanelView extends FrameLayout implements OnItemClickListener, RecentsCallback,
Michael Jurka80343f62012-10-18 13:13:46 +020069 StatusBarPanel, Animator.AnimatorListener {
Michael Jurka3cd0a592011-08-16 12:40:30 -070070 static final String TAG = "RecentsPanelView";
Dianne Hackbornfc8fa632011-08-17 16:20:47 -070071 static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
Michael Jurkacb466432012-04-03 05:22:45 -070072 private PopupMenu mPopup;
Jim Miller85babff2011-01-11 14:26:03 -080073 private View mRecentsScrim;
Michael Jurka6d667082011-09-16 17:04:40 -070074 private View mRecentsNoApps;
Jim Millerc0d27312011-07-14 18:54:01 -070075 private ViewGroup mRecentsContainer;
Daniel Sandler328310c2011-09-23 15:56:52 -040076 private StatusBarTouchProxy mStatusBarTouchProxy;
Peter Ng622a9762011-08-29 10:56:53 -070077
Jim Miller85babff2011-01-11 14:26:03 -080078 private boolean mShowing;
Michael Jurka99a96552012-01-27 17:23:38 -080079 private boolean mWaitingToShow;
Michael Jurka9bdaada2012-10-01 13:58:29 +020080 private ViewHolder mItemToAnimateInWhenWindowAnimationIsFinished;
Michael Jurkad894c8c2012-11-20 16:46:09 -080081 private boolean mAnimateIconOfFirstTask;
Michael Jurka80343f62012-10-18 13:13:46 +020082 private boolean mWaitingForWindowAnimation;
Michael Jurkad894c8c2012-11-20 16:46:09 -080083 private long mWindowAnimationStartTime;
Michael Jurka21385cd2012-05-03 10:57:31 -070084
Michael Jurkaab48b682011-09-12 15:39:45 -070085 private RecentTasksLoader mRecentTasksLoader;
86 private ArrayList<TaskDescription> mRecentTaskDescriptions;
87 private TaskDescriptionAdapter mListAdapter;
88 private int mThumbnailWidth;
Michael Jurkabfd24ac2011-11-13 13:50:38 -080089 private boolean mFitThumbnailToXY;
Daniel Sandler4a066c52012-04-20 14:49:13 -040090 private int mRecentItemLayoutId;
Michael Jurkac016aaa2012-06-05 17:22:24 -070091 private boolean mHighEndGfx;
Dianne Hackborneeb1dca2011-09-08 13:30:11 -070092
Michael Jurka4eaa9832012-02-29 15:51:49 -080093 public static interface RecentsScrollView {
94 public int numItemsInOneScreenful();
95 public void setAdapter(TaskDescriptionAdapter adapter);
96 public void setCallback(RecentsCallback callback);
97 public void setMinSwipeAlpha(float minAlpha);
Michael Jurkae5923632012-10-03 15:29:36 +020098 public View findViewForTask(int persistentTaskId);
Michael Jurka4eaa9832012-02-29 15:51:49 -080099 }
100
Jim Millerc0d27312011-07-14 18:54:01 -0700101 private final class OnLongClickDelegate implements View.OnLongClickListener {
102 View mOtherView;
103 OnLongClickDelegate(View other) {
104 mOtherView = other;
105 }
106 public boolean onLongClick(View v) {
107 return mOtherView.performLongClick();
108 }
109 }
110
Jim Millerb5a2b292011-03-01 16:14:59 -0800111 /* package */ final static class ViewHolder {
Jim Millerc0d27312011-07-14 18:54:01 -0700112 View thumbnailView;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700113 ImageView thumbnailViewImage;
Michael Jurka412cba82011-10-17 09:05:00 -0700114 Bitmap thumbnailViewImageBitmap;
Jim Miller9f0f0e02011-05-17 20:06:29 -0700115 ImageView iconView;
116 TextView labelView;
117 TextView descriptionView;
Michael Jurka9bdaada2012-10-01 13:58:29 +0200118 View calloutLine;
Michael Jurkaab48b682011-09-12 15:39:45 -0700119 TaskDescription taskDescription;
Michael Jurka99a96552012-01-27 17:23:38 -0800120 boolean loadedThumbnailAndIcon;
Jim Miller5fda69c2011-02-16 15:17:11 -0800121 }
122
Michael Jurkaab48b682011-09-12 15:39:45 -0700123 /* package */ final class TaskDescriptionAdapter extends BaseAdapter {
Jim Miller5fda69c2011-02-16 15:17:11 -0800124 private LayoutInflater mInflater;
125
Michael Jurkaab48b682011-09-12 15:39:45 -0700126 public TaskDescriptionAdapter(Context context) {
Jim Miller5fda69c2011-02-16 15:17:11 -0800127 mInflater = LayoutInflater.from(context);
128 }
129
130 public int getCount() {
Michael Jurkaab48b682011-09-12 15:39:45 -0700131 return mRecentTaskDescriptions != null ? mRecentTaskDescriptions.size() : 0;
Jim Miller5fda69c2011-02-16 15:17:11 -0800132 }
133
134 public Object getItem(int position) {
135 return position; // we only need the index
136 }
137
138 public long getItemId(int position) {
139 return position; // we just need something unique for this position
140 }
141
Michael Jurka99a96552012-01-27 17:23:38 -0800142 public View createView(ViewGroup parent) {
Daniel Sandler4a066c52012-04-20 14:49:13 -0400143 View convertView = mInflater.inflate(mRecentItemLayoutId, parent, false);
Michael Jurka99a96552012-01-27 17:23:38 -0800144 ViewHolder holder = new ViewHolder();
145 holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail);
146 holder.thumbnailViewImage =
147 (ImageView) convertView.findViewById(R.id.app_thumbnail_image);
148 // If we set the default thumbnail now, we avoid an onLayout when we update
149 // the thumbnail later (if they both have the same dimensions)
Michael Jurka80343f62012-10-18 13:13:46 +0200150 updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
Michael Jurka99a96552012-01-27 17:23:38 -0800151 holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
Michael Jurka80343f62012-10-18 13:13:46 +0200152 holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
Michael Jurka99a96552012-01-27 17:23:38 -0800153 holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
Michael Jurka9bdaada2012-10-01 13:58:29 +0200154 holder.calloutLine = convertView.findViewById(R.id.recents_callout_line);
Michael Jurka99a96552012-01-27 17:23:38 -0800155 holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
156
157 convertView.setTag(holder);
158 return convertView;
159 }
160
161 public View getView(int position, View convertView, ViewGroup parent) {
162 if (convertView == null) {
163 convertView = createView(parent);
164 }
165 ViewHolder holder = (ViewHolder) convertView.getTag();
Jim Miller5fda69c2011-02-16 15:17:11 -0800166
Michael Jurkaab48b682011-09-12 15:39:45 -0700167 // index is reverse since most recent appears at the bottom...
168 final int index = mRecentTaskDescriptions.size() - position - 1;
Jim Miller5fda69c2011-02-16 15:17:11 -0800169
Michael Jurka412cba82011-10-17 09:05:00 -0700170 final TaskDescription td = mRecentTaskDescriptions.get(index);
Michael Jurka99a96552012-01-27 17:23:38 -0800171
Michael Jurka412cba82011-10-17 09:05:00 -0700172 holder.labelView.setText(td.getLabel());
173 holder.thumbnailView.setContentDescription(td.getLabel());
Michael Jurka99a96552012-01-27 17:23:38 -0800174 holder.loadedThumbnailAndIcon = td.isLoaded();
175 if (td.isLoaded()) {
176 updateThumbnail(holder, td.getThumbnail(), true, false);
177 updateIcon(holder, td.getIcon(), true, false);
Michael Jurka99a96552012-01-27 17:23:38 -0800178 }
Michael Jurka9bdaada2012-10-01 13:58:29 +0200179 if (index == 0) {
Michael Jurkad894c8c2012-11-20 16:46:09 -0800180 if (mAnimateIconOfFirstTask) {
Michael Jurkaa9240762012-10-17 13:02:55 +0200181 if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
Michael Jurkafe09ad82012-10-22 13:58:38 -0700182 holder.iconView.setAlpha(1f);
183 holder.iconView.setTranslationX(0f);
184 holder.iconView.setTranslationY(0f);
185 holder.labelView.setAlpha(1f);
186 holder.labelView.setTranslationX(0f);
187 holder.labelView.setTranslationY(0f);
188 if (holder.calloutLine != null) {
189 holder.calloutLine.setAlpha(1f);
190 holder.calloutLine.setTranslationX(0f);
191 holder.calloutLine.setTranslationY(0f);
Michael Jurkaa9240762012-10-17 13:02:55 +0200192 }
193 }
Michael Jurka9bdaada2012-10-01 13:58:29 +0200194 mItemToAnimateInWhenWindowAnimationIsFinished = holder;
195 final int translation = -getResources().getDimensionPixelSize(
196 R.dimen.status_bar_recents_app_icon_translate_distance);
197 final Configuration config = getResources().getConfiguration();
198 if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
Michael Jurkafe09ad82012-10-22 13:58:38 -0700199 holder.iconView.setAlpha(0f);
200 holder.iconView.setTranslationX(translation);
201 holder.labelView.setAlpha(0f);
202 holder.labelView.setTranslationX(translation);
203 holder.calloutLine.setAlpha(0f);
204 holder.calloutLine.setTranslationX(translation);
Michael Jurka9bdaada2012-10-01 13:58:29 +0200205 } else {
206 holder.iconView.setAlpha(0f);
207 holder.iconView.setTranslationY(translation);
208 }
Michael Jurkad894c8c2012-11-20 16:46:09 -0800209 if (!mWaitingForWindowAnimation) {
210 animateInIconOfFirstTask();
211 }
Michael Jurka9bdaada2012-10-01 13:58:29 +0200212 }
213 }
Michael Jurkaab48b682011-09-12 15:39:45 -0700214
Michael Jurka412cba82011-10-17 09:05:00 -0700215 holder.thumbnailView.setTag(td);
Jim Millerc0d27312011-07-14 18:54:01 -0700216 holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView));
Michael Jurka412cba82011-10-17 09:05:00 -0700217 holder.taskDescription = td;
Jim Miller5fda69c2011-02-16 15:17:11 -0800218 return convertView;
219 }
Michael Jurka99a96552012-01-27 17:23:38 -0800220
221 public void recycleView(View v) {
222 ViewHolder holder = (ViewHolder) v.getTag();
223 updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
224 holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
225 holder.iconView.setVisibility(INVISIBLE);
Michael Jurkad894c8c2012-11-20 16:46:09 -0800226 holder.iconView.animate().cancel();
Michael Jurka99a96552012-01-27 17:23:38 -0800227 holder.labelView.setText(null);
Michael Jurkad894c8c2012-11-20 16:46:09 -0800228 holder.labelView.animate().cancel();
Michael Jurka99a96552012-01-27 17:23:38 -0800229 holder.thumbnailView.setContentDescription(null);
230 holder.thumbnailView.setTag(null);
231 holder.thumbnailView.setOnLongClickListener(null);
232 holder.thumbnailView.setVisibility(INVISIBLE);
Michael Jurkafe09ad82012-10-22 13:58:38 -0700233 holder.iconView.setAlpha(1f);
234 holder.iconView.setTranslationX(0f);
235 holder.iconView.setTranslationY(0f);
236 holder.labelView.setAlpha(1f);
237 holder.labelView.setTranslationX(0f);
238 holder.labelView.setTranslationY(0f);
239 if (holder.calloutLine != null) {
240 holder.calloutLine.setAlpha(1f);
241 holder.calloutLine.setTranslationX(0f);
242 holder.calloutLine.setTranslationY(0f);
Michael Jurkad894c8c2012-11-20 16:46:09 -0800243 holder.calloutLine.animate().cancel();
Michael Jurkafe09ad82012-10-22 13:58:38 -0700244 }
Michael Jurka99a96552012-01-27 17:23:38 -0800245 holder.taskDescription = null;
246 holder.loadedThumbnailAndIcon = false;
247 }
248 }
249
Michael Jurka8b2e37e2012-05-08 20:06:13 -0700250 public RecentsPanelView(Context context, AttributeSet attrs) {
251 this(context, attrs, 0);
252 }
253
254 public RecentsPanelView(Context context, AttributeSet attrs, int defStyle) {
255 super(context, attrs, defStyle);
Michael Jurka8b2e37e2012-05-08 20:06:13 -0700256 updateValuesFromResources();
257
258 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecentsPanelView,
259 defStyle, 0);
260
261 mRecentItemLayoutId = a.getResourceId(R.styleable.RecentsPanelView_recentItemLayout, 0);
Michael Jurka80343f62012-10-18 13:13:46 +0200262 mRecentTasksLoader = RecentTasksLoader.getInstance(context);
Michael Jurka8b2e37e2012-05-08 20:06:13 -0700263 a.recycle();
264 }
265
Michael Jurka99a96552012-01-27 17:23:38 -0800266 public int numItemsInOneScreenful() {
Michael Jurka4eaa9832012-02-29 15:51:49 -0800267 if (mRecentsContainer instanceof RecentsScrollView){
268 RecentsScrollView scrollView
269 = (RecentsScrollView) mRecentsContainer;
Michael Jurka99a96552012-01-27 17:23:38 -0800270 return scrollView.numItemsInOneScreenful();
Michael Jurka4eaa9832012-02-29 15:51:49 -0800271 } else {
Michael Jurka99a96552012-01-27 17:23:38 -0800272 throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView");
273 }
Jim Miller5fda69c2011-02-16 15:17:11 -0800274 }
275
Daniel Sandler328310c2011-09-23 15:56:52 -0400276 private boolean pointInside(int x, int y, View v) {
277 final int l = v.getLeft();
278 final int r = v.getRight();
279 final int t = v.getTop();
280 final int b = v.getBottom();
Jim Miller44c66fe2010-10-20 18:32:52 -0700281 return x >= l && x < r && y >= t && y < b;
282 }
283
Daniel Sandler328310c2011-09-23 15:56:52 -0400284 public boolean isInContentArea(int x, int y) {
Michael Jurkab144bd72012-01-12 06:56:39 -0800285 if (pointInside(x, y, mRecentsContainer)) {
286 return true;
287 } else if (mStatusBarTouchProxy != null &&
288 pointInside(x, y, mStatusBarTouchProxy)) {
289 return true;
290 } else {
291 return false;
292 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400293 }
294
Michael Jurkacb2522c2012-04-13 09:32:47 -0700295 public void show(boolean show) {
Michael Jurka80343f62012-10-18 13:13:46 +0200296 show(show, null, false, false);
Michael Jurkacb2522c2012-04-13 09:32:47 -0700297 }
298
299 public void show(boolean show, ArrayList<TaskDescription> recentTaskDescriptions,
Michael Jurkad894c8c2012-11-20 16:46:09 -0800300 boolean firstScreenful, boolean animateIconOfFirstTask) {
301 mAnimateIconOfFirstTask = animateIconOfFirstTask;
302 mWaitingForWindowAnimation = animateIconOfFirstTask;
Michael Jurka99a96552012-01-27 17:23:38 -0800303 if (show) {
304 mWaitingToShow = true;
Michael Jurkacb2522c2012-04-13 09:32:47 -0700305 refreshRecentTasksList(recentTaskDescriptions, firstScreenful);
Michael Jurka99a96552012-01-27 17:23:38 -0800306 showIfReady();
307 } else {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700308 showImpl(false);
Michael Jurka99a96552012-01-27 17:23:38 -0800309 }
310 }
311
312 private void showIfReady() {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700313 // mWaitingToShow => there was a touch up on the recents button
314 // mRecentTaskDescriptions != null => we've created views for the first screenful of items
315 if (mWaitingToShow && mRecentTaskDescriptions != null) {
316 showImpl(true);
Michael Jurka99a96552012-01-27 17:23:38 -0800317 }
Michael Jurkaab48b682011-09-12 15:39:45 -0700318 }
319
Michael Jurka56a57832012-05-14 13:24:43 -0700320 static void sendCloseSystemWindows(Context context, String reason) {
321 if (ActivityManagerNative.isSystemReady()) {
322 try {
323 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
324 } catch (RemoteException e) {
325 }
326 }
327 }
328
Michael Jurkacb2522c2012-04-13 09:32:47 -0700329 private void showImpl(boolean show) {
Michael Jurka56a57832012-05-14 13:24:43 -0700330 sendCloseSystemWindows(mContext, BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
331
Michael Jurkacb2522c2012-04-13 09:32:47 -0700332 mShowing = show;
333
Michael Jurka7daf95d2011-09-30 11:07:30 -0700334 if (show) {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700335 // if there are no apps, bring up a "No recent apps" message
336 boolean noApps = mRecentTaskDescriptions != null
337 && (mRecentTaskDescriptions.size() == 0);
338 mRecentsNoApps.setAlpha(1f);
339 mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
Michael Jurka7daf95d2011-09-30 11:07:30 -0700340
Michael Jurkaab48b682011-09-12 15:39:45 -0700341 onAnimationEnd(null);
Michael Jurkae9166ed2011-07-27 18:23:18 -0700342 setFocusable(true);
343 setFocusableInTouchMode(true);
344 requestFocus();
Michael Jurkacb466432012-04-03 05:22:45 -0700345 } else {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700346 mWaitingToShow = false;
347 // call onAnimationEnd() and clearRecentTasksList() in onUiHidden()
Michael Jurkacb466432012-04-03 05:22:45 -0700348 if (mPopup != null) {
349 mPopup.dismiss();
350 }
Michael Jurkae9166ed2011-07-27 18:23:18 -0700351 }
Jim Miller85babff2011-01-11 14:26:03 -0800352 }
353
Michael Jurkacb2522c2012-04-13 09:32:47 -0700354 public void onUiHidden() {
355 if (!mShowing && mRecentTaskDescriptions != null) {
356 onAnimationEnd(null);
357 clearRecentTasksList();
358 }
Michael Jurkac6461ca2011-09-02 12:12:15 -0700359 }
360
Michael Jurkacb2522c2012-04-13 09:32:47 -0700361 public void dismiss() {
362 ((RecentsActivity) mContext).dismissAndGoHome();
363 }
364
365 public void dismissAndGoBack() {
366 ((RecentsActivity) mContext).dismissAndGoBack();
Michael Jurka8b098662011-09-01 17:00:53 -0700367 }
368
Michael Jurka3b1fc472011-06-13 10:54:40 -0700369 public void onAnimationCancel(Animator animation) {
370 }
371
372 public void onAnimationEnd(Animator animation) {
373 if (mShowing) {
374 final LayoutTransition transitioner = new LayoutTransition();
375 ((ViewGroup)mRecentsContainer).setLayoutTransition(transitioner);
376 createCustomAnimations(transitioner);
377 } else {
378 ((ViewGroup)mRecentsContainer).setLayoutTransition(null);
379 }
380 }
381
382 public void onAnimationRepeat(Animator animation) {
383 }
384
385 public void onAnimationStart(Animator animation) {
386 }
387
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700388 @Override
389 public boolean dispatchHoverEvent(MotionEvent event) {
390 // Ignore hover events outside of this panel bounds since such events
391 // generate spurious accessibility events with the panel content when
392 // tapping outside of it, thus confusing the user.
393 final int x = (int) event.getX();
394 final int y = (int) event.getY();
395 if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
396 return super.dispatchHoverEvent(event);
397 }
398 return true;
399 }
400
Jim Miller85babff2011-01-11 14:26:03 -0800401 /**
402 * Whether the panel is showing, or, if it's animating, whether it will be
403 * when the animation is done.
404 */
405 public boolean isShowing() {
406 return mShowing;
407 }
408
Daniel Sandler328310c2011-09-23 15:56:52 -0400409 public void setStatusBarView(View statusBarView) {
410 if (mStatusBarTouchProxy != null) {
411 mStatusBarTouchProxy.setStatusBar(statusBarView);
412 }
413 }
414
415 public void setRecentTasksLoader(RecentTasksLoader loader) {
416 mRecentTasksLoader = loader;
417 }
418
Michael Jurkaab48b682011-09-12 15:39:45 -0700419 public void updateValuesFromResources() {
Michael Jurkabfd24ac2011-11-13 13:50:38 -0800420 final Resources res = mContext.getResources();
421 mThumbnailWidth = Math.round(res.getDimension(R.dimen.status_bar_recents_thumbnail_width));
422 mFitThumbnailToXY = res.getBoolean(R.bool.config_recents_thumbnail_image_fits_to_xy);
Jim Miller44c66fe2010-10-20 18:32:52 -0700423 }
424
425 @Override
426 protected void onFinishInflate() {
427 super.onFinishInflate();
Daniel Sandler4a066c52012-04-20 14:49:13 -0400428
Jim Millerc0d27312011-07-14 18:54:01 -0700429 mRecentsContainer = (ViewGroup) findViewById(R.id.recents_container);
Daniel Sandler328310c2011-09-23 15:56:52 -0400430 mStatusBarTouchProxy = (StatusBarTouchProxy) findViewById(R.id.status_bar_touch_proxy);
Michael Jurkaab48b682011-09-12 15:39:45 -0700431 mListAdapter = new TaskDescriptionAdapter(mContext);
Michael Jurka4eaa9832012-02-29 15:51:49 -0800432 if (mRecentsContainer instanceof RecentsScrollView){
433 RecentsScrollView scrollView
434 = (RecentsScrollView) mRecentsContainer;
Jim Miller9f0f0e02011-05-17 20:06:29 -0700435 scrollView.setAdapter(mListAdapter);
436 scrollView.setCallback(this);
Michael Jurka4eaa9832012-02-29 15:51:49 -0800437 } else {
Michael Jurka3cd0a592011-08-16 12:40:30 -0700438 throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView");
Jim Miller9f0f0e02011-05-17 20:06:29 -0700439 }
Jim Miller5fda69c2011-02-16 15:17:11 -0800440
Michael Jurka6d667082011-09-16 17:04:40 -0700441 mRecentsScrim = findViewById(R.id.recents_bg_protect);
442 mRecentsNoApps = findViewById(R.id.recents_no_apps);
Jim Millere5c16ab2010-12-03 19:18:38 -0800443
Michael Jurkaf16fc512012-02-27 15:02:23 -0800444 if (mRecentsScrim != null) {
Jeff Brown98365d72012-08-19 20:30:52 -0700445 mHighEndGfx = ActivityManager.isHighEndGfx();
Michael Jurkac016aaa2012-06-05 17:22:24 -0700446 if (!mHighEndGfx) {
Michael Jurkad5895a72012-05-12 13:24:58 -0700447 mRecentsScrim.setBackground(null);
Michael Jurkaf16fc512012-02-27 15:02:23 -0800448 } else if (mRecentsScrim.getBackground() instanceof BitmapDrawable) {
449 // In order to save space, we make the background texture repeat in the Y direction
450 ((BitmapDrawable) mRecentsScrim.getBackground()).setTileModeY(TileMode.REPEAT);
451 }
Jim Millere5c16ab2010-12-03 19:18:38 -0800452 }
453 }
454
Michael Jurka4eaa9832012-02-29 15:51:49 -0800455 public void setMinSwipeAlpha(float minAlpha) {
456 if (mRecentsContainer instanceof RecentsScrollView){
457 RecentsScrollView scrollView
458 = (RecentsScrollView) mRecentsContainer;
459 scrollView.setMinSwipeAlpha(minAlpha);
460 }
461 }
462
Jim Miller9f0f0e02011-05-17 20:06:29 -0700463 private void createCustomAnimations(LayoutTransition transitioner) {
Chet Haase212f6252011-08-12 09:19:10 -0700464 transitioner.setDuration(200);
465 transitioner.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
466 transitioner.setAnimator(LayoutTransition.DISAPPEARING, null);
Jim Miller9f0f0e02011-05-17 20:06:29 -0700467 }
468
Michael Jurka99a96552012-01-27 17:23:38 -0800469 private void updateIcon(ViewHolder h, Drawable icon, boolean show, boolean anim) {
470 if (icon != null) {
471 h.iconView.setImageDrawable(icon);
472 if (show && h.iconView.getVisibility() != View.VISIBLE) {
473 if (anim) {
474 h.iconView.setAnimation(
475 AnimationUtils.loadAnimation(mContext, R.anim.recent_appear));
476 }
477 h.iconView.setVisibility(View.VISIBLE);
478 }
479 }
480 }
481
Michael Jurka412cba82011-10-17 09:05:00 -0700482 private void updateThumbnail(ViewHolder h, Bitmap thumbnail, boolean show, boolean anim) {
Michael Jurkaab48b682011-09-12 15:39:45 -0700483 if (thumbnail != null) {
484 // Should remove the default image in the frame
485 // that this now covers, to improve scrolling speed.
486 // That can't be done until the anim is complete though.
487 h.thumbnailViewImage.setImageBitmap(thumbnail);
Michael Jurka412cba82011-10-17 09:05:00 -0700488
489 // scale the image to fill the full width of the ImageView. do this only if
490 // we haven't set a bitmap before, or if the bitmap size has changed
491 if (h.thumbnailViewImageBitmap == null ||
492 h.thumbnailViewImageBitmap.getWidth() != thumbnail.getWidth() ||
493 h.thumbnailViewImageBitmap.getHeight() != thumbnail.getHeight()) {
Michael Jurkabfd24ac2011-11-13 13:50:38 -0800494 if (mFitThumbnailToXY) {
495 h.thumbnailViewImage.setScaleType(ScaleType.FIT_XY);
496 } else {
497 Matrix scaleMatrix = new Matrix();
498 float scale = mThumbnailWidth / (float) thumbnail.getWidth();
499 scaleMatrix.setScale(scale, scale);
500 h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
501 h.thumbnailViewImage.setImageMatrix(scaleMatrix);
502 }
Jim Miller44c66fe2010-10-20 18:32:52 -0700503 }
Michael Jurka412cba82011-10-17 09:05:00 -0700504 if (show && h.thumbnailView.getVisibility() != View.VISIBLE) {
505 if (anim) {
506 h.thumbnailView.setAnimation(
507 AnimationUtils.loadAnimation(mContext, R.anim.recent_appear));
508 }
509 h.thumbnailView.setVisibility(View.VISIBLE);
510 }
511 h.thumbnailViewImageBitmap = thumbnail;
Jim Miller44c66fe2010-10-20 18:32:52 -0700512 }
Jim Millerfefef312010-11-09 14:08:39 -0800513 }
514
Michael Jurka99a96552012-01-27 17:23:38 -0800515 void onTaskThumbnailLoaded(TaskDescription td) {
516 synchronized (td) {
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700517 if (mRecentsContainer != null) {
518 ViewGroup container = mRecentsContainer;
Michael Jurka4eaa9832012-02-29 15:51:49 -0800519 if (container instanceof RecentsScrollView) {
Michael Jurka99a96552012-01-27 17:23:38 -0800520 container = (ViewGroup) container.findViewById(
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700521 R.id.recents_linear_layout);
522 }
523 // Look for a view showing this thumbnail, to update.
Michael Jurka99a96552012-01-27 17:23:38 -0800524 for (int i=0; i < container.getChildCount(); i++) {
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700525 View v = container.getChildAt(i);
526 if (v.getTag() instanceof ViewHolder) {
527 ViewHolder h = (ViewHolder)v.getTag();
Michael Jurka99a96552012-01-27 17:23:38 -0800528 if (!h.loadedThumbnailAndIcon && h.taskDescription == td) {
Michael Jurka412cba82011-10-17 09:05:00 -0700529 // only fade in the thumbnail if recents is already visible-- we
530 // show it immediately otherwise
Michael Jurka99a96552012-01-27 17:23:38 -0800531 //boolean animateShow = mShowing &&
532 // mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
533 boolean animateShow = false;
534 updateIcon(h, td.getIcon(), true, animateShow);
535 updateThumbnail(h, td.getThumbnail(), true, animateShow);
536 h.loadedThumbnailAndIcon = true;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700537 }
538 }
539 }
540 }
Craig Mautnerca6da002012-09-20 14:54:37 -0700541 }
Michael Jurka99a96552012-01-27 17:23:38 -0800542 showIfReady();
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700543 }
544
Michael Jurkad894c8c2012-11-20 16:46:09 -0800545 private void animateInIconOfFirstTask() {
546 if (mItemToAnimateInWhenWindowAnimationIsFinished != null &&
547 !mRecentTasksLoader.isFirstScreenful()) {
548 int timeSinceWindowAnimation =
549 (int) (System.currentTimeMillis() - mWindowAnimationStartTime);
550 final int minStartDelay = 150;
551 final int startDelay = Math.max(0, Math.min(
552 minStartDelay - timeSinceWindowAnimation, minStartDelay));
Michael Jurka9bdaada2012-10-01 13:58:29 +0200553 final int duration = 250;
554 final ViewHolder holder = mItemToAnimateInWhenWindowAnimationIsFinished;
555 final TimeInterpolator cubic = new DecelerateInterpolator(1.5f);
556 for (View v :
557 new View[] { holder.iconView, holder.labelView, holder.calloutLine }) {
558 if (v != null) {
559 v.animate().translationX(0).translationY(0).alpha(1f).setStartDelay(startDelay)
560 .setDuration(duration).setInterpolator(cubic);
561 }
562 }
563 mItemToAnimateInWhenWindowAnimationIsFinished = null;
Michael Jurkad894c8c2012-11-20 16:46:09 -0800564 mAnimateIconOfFirstTask = false;
Michael Jurka9bdaada2012-10-01 13:58:29 +0200565 }
566 }
567
Michael Jurkad894c8c2012-11-20 16:46:09 -0800568 public void onWindowAnimationStart() {
569 mWaitingForWindowAnimation = false;
570 mWindowAnimationStartTime = System.currentTimeMillis();
571 animateInIconOfFirstTask();
572 }
573
Michael Jurka412cba82011-10-17 09:05:00 -0700574 public void clearRecentTasksList() {
575 // Clear memory used by screenshots
Michael Jurkacb2522c2012-04-13 09:32:47 -0700576 if (mRecentTaskDescriptions != null) {
577 mRecentTasksLoader.cancelLoadingThumbnailsAndIcons(this);
578 onTaskLoadingCancelled();
579 }
580 }
581
582 public void onTaskLoadingCancelled() {
583 // Gets called by RecentTasksLoader when it's cancelled
584 if (mRecentTaskDescriptions != null) {
585 mRecentTaskDescriptions = null;
Michael Jurka412cba82011-10-17 09:05:00 -0700586 mListAdapter.notifyDataSetInvalidated();
Michael Jurka412cba82011-10-17 09:05:00 -0700587 }
588 }
589
Craig Mautnerca6da002012-09-20 14:54:37 -0700590 public void refreshViews() {
591 mListAdapter.notifyDataSetInvalidated();
592 updateUiElements();
593 showIfReady();
594 }
595
Michael Jurka412cba82011-10-17 09:05:00 -0700596 public void refreshRecentTasksList() {
Michael Jurka99a96552012-01-27 17:23:38 -0800597 refreshRecentTasksList(null, false);
Michael Jurka412cba82011-10-17 09:05:00 -0700598 }
599
Michael Jurka99a96552012-01-27 17:23:38 -0800600 private void refreshRecentTasksList(
601 ArrayList<TaskDescription> recentTasksList, boolean firstScreenful) {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700602 if (mRecentTaskDescriptions == null && recentTasksList != null) {
603 onTasksLoaded(recentTasksList, firstScreenful);
604 } else {
605 mRecentTasksLoader.loadTasksInBackground();
Michael Jurka412cba82011-10-17 09:05:00 -0700606 }
Michael Jurkaab48b682011-09-12 15:39:45 -0700607 }
Michael Jurka7daf95d2011-09-30 11:07:30 -0700608
Michael Jurkacb2522c2012-04-13 09:32:47 -0700609 public void onTasksLoaded(ArrayList<TaskDescription> tasks, boolean firstScreenful) {
Michael Jurka99a96552012-01-27 17:23:38 -0800610 if (mRecentTaskDescriptions == null) {
Craig Mautnerbb1449b2012-03-23 16:11:14 -0700611 mRecentTaskDescriptions = new ArrayList<TaskDescription>(tasks);
Michael Jurka99a96552012-01-27 17:23:38 -0800612 } else {
613 mRecentTaskDescriptions.addAll(tasks);
614 }
Michael Jurka7ed267f2012-10-09 17:03:30 +0200615 if (((RecentsActivity) mContext).isActivityShowing()) {
Craig Mautnerca6da002012-09-20 14:54:37 -0700616 refreshViews();
617 }
Michael Jurka99a96552012-01-27 17:23:38 -0800618 }
619
Craig Mautnerca6da002012-09-20 14:54:37 -0700620 private void updateUiElements() {
Dianne Hackborn8da429e2012-09-23 12:52:19 -0700621 final int items = mRecentTaskDescriptions != null
622 ? mRecentTaskDescriptions.size() : 0;
Michael Jurkaab48b682011-09-12 15:39:45 -0700623
624 mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
Michael Jurkaab48b682011-09-12 15:39:45 -0700625
626 // Set description for accessibility
Dianne Hackborn8da429e2012-09-23 12:52:19 -0700627 int numRecentApps = mRecentTaskDescriptions != null
628 ? mRecentTaskDescriptions.size() : 0;
Michael Jurka7daf95d2011-09-30 11:07:30 -0700629 String recentAppsAccessibilityDescription;
630 if (numRecentApps == 0) {
631 recentAppsAccessibilityDescription =
632 getResources().getString(R.string.status_bar_no_recent_apps);
633 } else {
634 recentAppsAccessibilityDescription = getResources().getQuantityString(
635 R.plurals.status_bar_accessibility_recent_apps, numRecentApps, numRecentApps);
636 }
637 setContentDescription(recentAppsAccessibilityDescription);
Jim Miller44c66fe2010-10-20 18:32:52 -0700638 }
639
Michael Jurkae5923632012-10-03 15:29:36 +0200640 public boolean simulateClick(int persistentTaskId) {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700641 if (mRecentsContainer instanceof RecentsScrollView){
642 RecentsScrollView scrollView
643 = (RecentsScrollView) mRecentsContainer;
Michael Jurkae5923632012-10-03 15:29:36 +0200644 View v = scrollView.findViewForTask(persistentTaskId);
Michael Jurkacb2522c2012-04-13 09:32:47 -0700645 if (v != null) {
646 handleOnClick(v);
647 return true;
648 }
649 }
650 return false;
651 }
Michael Jurkac016aaa2012-06-05 17:22:24 -0700652
Jim Miller9f0f0e02011-05-17 20:06:29 -0700653 public void handleOnClick(View view) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700654 ViewHolder holder = (ViewHolder)view.getTag();
655 TaskDescription ad = holder.taskDescription;
Jim Miller9f0f0e02011-05-17 20:06:29 -0700656 final Context context = view.getContext();
Jim Millere5c16ab2010-12-03 19:18:38 -0800657 final ActivityManager am = (ActivityManager)
Jim Miller9f0f0e02011-05-17 20:06:29 -0700658 context.getSystemService(Context.ACTIVITY_SERVICE);
Michael Jurkac016aaa2012-06-05 17:22:24 -0700659 Bitmap bm = holder.thumbnailViewImageBitmap;
660 boolean usingDrawingCache;
661 if (bm.getWidth() == holder.thumbnailViewImage.getWidth() &&
662 bm.getHeight() == holder.thumbnailViewImage.getHeight()) {
663 usingDrawingCache = false;
664 } else {
665 holder.thumbnailViewImage.setDrawingCacheEnabled(true);
666 bm = holder.thumbnailViewImage.getDrawingCache();
667 usingDrawingCache = true;
668 }
Michael Jurka482f1592012-09-13 11:05:59 -0700669 Bundle opts = (bm == null) ?
670 null :
671 ActivityOptions.makeThumbnailScaleUpAnimation(
672 holder.thumbnailViewImage, bm, 0, 0, null).toBundle();
Michael Jurkacb2522c2012-04-13 09:32:47 -0700673
674 show(false);
Jim Miller9f0f0e02011-05-17 20:06:29 -0700675 if (ad.taskId >= 0) {
Dianne Hackbornb6777462010-11-12 12:43:22 -0800676 // This is an active task; it should just go to the foreground.
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700677 am.moveTaskToFront(ad.taskId, ActivityManager.MOVE_TASK_WITH_HOME,
Michael Jurka482f1592012-09-13 11:05:59 -0700678 opts);
Dianne Hackbornb6777462010-11-12 12:43:22 -0800679 } else {
680 Intent intent = ad.intent;
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800681 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700682 | Intent.FLAG_ACTIVITY_TASK_ON_HOME
683 | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackbornb6777462010-11-12 12:43:22 -0800684 if (DEBUG) Log.v(TAG, "Starting activity " + intent);
Michael Jurka482f1592012-09-13 11:05:59 -0700685 context.startActivityAsUser(intent, opts,
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700686 new UserHandle(UserHandle.USER_CURRENT));
Dianne Hackbornb6777462010-11-12 12:43:22 -0800687 }
Michael Jurkab9a38c52012-06-14 11:57:50 -0700688 if (usingDrawingCache) {
Michael Jurkac016aaa2012-06-05 17:22:24 -0700689 holder.thumbnailViewImage.setDrawingCacheEnabled(false);
690 }
Jim Millerf1e22e52011-01-26 15:39:51 -0800691 }
Jim Miller9f0f0e02011-05-17 20:06:29 -0700692
693 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
694 handleOnClick(view);
695 }
696
Michael Jurka07d40462011-07-19 10:54:38 -0700697 public void handleSwipe(View view) {
Michael Jurkaab48b682011-09-12 15:39:45 -0700698 TaskDescription ad = ((ViewHolder) view.getTag()).taskDescription;
Michael Jurkaa8eac1d2012-04-30 15:54:19 -0700699 if (ad == null) {
Michael Jurka9d69b442012-05-04 15:46:32 -0700700 Log.v(TAG, "Not able to find activity description for swiped task; view=" + view +
701 " tag=" + view.getTag());
702 return;
Michael Jurkaa8eac1d2012-04-30 15:54:19 -0700703 }
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700704 if (DEBUG) Log.v(TAG, "Jettison " + ad.getLabel());
Michael Jurkaab48b682011-09-12 15:39:45 -0700705 mRecentTaskDescriptions.remove(ad);
Michael Jurkae57922c2012-11-26 16:05:12 -0800706 mRecentTasksLoader.remove(ad);
Jim Miller9f0f0e02011-05-17 20:06:29 -0700707
708 // Handled by widget containers to enable LayoutTransitions properly
709 // mListAdapter.notifyDataSetChanged();
710
Michael Jurkaab48b682011-09-12 15:39:45 -0700711 if (mRecentTaskDescriptions.size() == 0) {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700712 dismissAndGoBack();
Jim Miller9f0f0e02011-05-17 20:06:29 -0700713 }
714
715 // Currently, either direction means the same thing, so ignore direction and remove
716 // the task.
717 final ActivityManager am = (ActivityManager)
718 mContext.getSystemService(Context.ACTIVITY_SERVICE);
Michael Jurkaa8eac1d2012-04-30 15:54:19 -0700719 if (am != null) {
720 am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
Jim Miller17377762011-10-11 15:33:34 -0700721
Michael Jurkaa8eac1d2012-04-30 15:54:19 -0700722 // Accessibility feedback
723 setContentDescription(
724 mContext.getString(R.string.accessibility_recents_item_dismissed, ad.getLabel()));
725 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
726 setContentDescription(null);
727 }
Jim Miller9f0f0e02011-05-17 20:06:29 -0700728 }
729
Jim Millerc0d27312011-07-14 18:54:01 -0700730 private void startApplicationDetailsActivity(String packageName) {
731 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
732 Uri.fromParts("package", packageName, null));
Adam Powell0fc5b2b2012-07-18 18:20:29 -0700733 intent.setComponent(intent.resolveActivity(mContext.getPackageManager()));
734 TaskStackBuilder.create(getContext())
735 .addNextIntentWithParentStack(intent).startActivities();
Jim Millerc0d27312011-07-14 18:54:01 -0700736 }
737
Michael Jurkacb466432012-04-03 05:22:45 -0700738 public boolean onInterceptTouchEvent(MotionEvent ev) {
739 if (mPopup != null) {
740 return true;
741 } else {
742 return super.onInterceptTouchEvent(ev);
743 }
744 }
745
Michael Jurkafaa790c2011-09-02 17:35:02 -0700746 public void handleLongPress(
747 final View selectedView, final View anchorView, final View thumbnailView) {
748 thumbnailView.setSelected(true);
Michael Jurkacb466432012-04-03 05:22:45 -0700749 final PopupMenu popup =
750 new PopupMenu(mContext, anchorView == null ? selectedView : anchorView);
751 mPopup = popup;
Jim Millerc0d27312011-07-14 18:54:01 -0700752 popup.getMenuInflater().inflate(R.menu.recent_popup_menu, popup.getMenu());
753 popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
754 public boolean onMenuItemClick(MenuItem item) {
755 if (item.getItemId() == R.id.recent_remove_item) {
756 mRecentsContainer.removeViewInLayout(selectedView);
757 } else if (item.getItemId() == R.id.recent_inspect_item) {
758 ViewHolder viewHolder = (ViewHolder) selectedView.getTag();
759 if (viewHolder != null) {
Michael Jurkaab48b682011-09-12 15:39:45 -0700760 final TaskDescription ad = viewHolder.taskDescription;
Jim Millerc0d27312011-07-14 18:54:01 -0700761 startApplicationDetailsActivity(ad.packageName);
Michael Jurkacb2522c2012-04-13 09:32:47 -0700762 show(false);
Jim Millerc0d27312011-07-14 18:54:01 -0700763 } else {
764 throw new IllegalStateException("Oops, no tag on view " + selectedView);
765 }
766 } else {
767 return false;
768 }
769 return true;
770 }
771 });
Michael Jurkafaa790c2011-09-02 17:35:02 -0700772 popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
773 public void onDismiss(PopupMenu menu) {
774 thumbnailView.setSelected(false);
Michael Jurkacb466432012-04-03 05:22:45 -0700775 mPopup = null;
Michael Jurkafaa790c2011-09-02 17:35:02 -0700776 }
777 });
Jim Millerc0d27312011-07-14 18:54:01 -0700778 popup.show();
Jim Miller9f0f0e02011-05-17 20:06:29 -0700779 }
Jim Miller44c66fe2010-10-20 18:32:52 -0700780}