blob: c10a2b14e74f056f72a622bc57f62343b0e1dc30 [file] [log] [blame]
Winson Chungb3347bb2010-08-19 14:51:28 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.launcher2;
18
Michael Jurka742574b2011-02-02 23:51:01 -080019import com.android.launcher.R;
20
Winson Chungcd4bc492010-12-09 18:52:32 -080021import android.animation.ObjectAnimator;
Winson Chung4dbea792011-05-05 14:21:32 -070022import android.content.ComponentName;
Winson Chungb3347bb2010-08-19 14:51:28 -070023import android.content.Context;
Winson Chung241c3b42010-08-25 16:53:03 -070024import android.content.pm.PackageManager;
25import android.content.pm.ResolveInfo;
Winson Chung59e1f9a2010-12-21 11:31:54 -080026import android.content.res.Resources;
Winson Chung64a3cd42010-09-17 16:47:33 -070027import android.content.res.TypedArray;
Winson Chungb3347bb2010-08-19 14:51:28 -070028import android.graphics.Bitmap;
Winson Chungb3347bb2010-08-19 14:51:28 -070029import android.graphics.Canvas;
Winson Chungb3347bb2010-08-19 14:51:28 -070030import android.graphics.Paint;
Michael Jurka0620bec2010-10-25 17:50:09 -070031import android.os.Handler;
32import android.os.HandlerThread;
33import android.os.Message;
Winson Chungb3347bb2010-08-19 14:51:28 -070034import android.util.AttributeSet;
Winson Chung97d85d22011-04-13 11:27:36 -070035import android.view.KeyEvent;
Winson Chung03c568e2010-08-19 17:16:59 -070036import android.widget.Checkable;
Michael Jurka742574b2011-02-02 23:51:01 -080037import android.widget.TextView;
Winson Chungc84001e2010-11-09 12:20:57 -080038
Winson Chung241c3b42010-08-25 16:53:03 -070039
Winson Chungb3347bb2010-08-19 14:51:28 -070040
41/**
42 * An icon on a PagedView, specifically for items in the launcher's paged view (with compound
43 * drawables on the top).
44 */
Michael Jurkac0759f52011-02-03 16:47:14 -080045public class PagedViewIcon extends CachedTextView implements Checkable {
Winson Chungb3347bb2010-08-19 14:51:28 -070046 private static final String TAG = "PagedViewIcon";
47
48 // holographic outline
49 private final Paint mPaint = new Paint();
50 private static HolographicOutlineHelper sHolographicOutlineHelper;
Winson Chung5f2aa4e2010-08-20 14:49:25 -070051 private Bitmap mCheckedOutline;
Winson Chungb3347bb2010-08-19 14:51:28 -070052 private Bitmap mHolographicOutline;
Michael Jurka0620bec2010-10-25 17:50:09 -070053 private Bitmap mIcon;
Winson Chungb3347bb2010-08-19 14:51:28 -070054
Winson Chung04998342011-01-05 13:54:43 -080055 private PagedViewIconCache.Key mIconCacheKey;
Winson Chung241c3b42010-08-25 16:53:03 -070056 private PagedViewIconCache mIconCache;
57
Winson Chung88127032010-12-13 12:11:33 -080058 private int mAlpha = 255;
Winson Chungb3347bb2010-08-19 14:51:28 -070059 private int mHolographicAlpha;
60
Winson Chungb46a2d12011-04-22 14:13:05 -070061 private boolean mHolographicEffectsEnabled;
Winson Chung03c568e2010-08-19 17:16:59 -070062 private boolean mIsChecked;
Winson Chungcd4bc492010-12-09 18:52:32 -080063 private ObjectAnimator mCheckedAlphaAnimator;
Winson Chung59e1f9a2010-12-21 11:31:54 -080064 private float mCheckedAlpha = 1.0f;
65 private int mCheckedFadeInDuration;
66 private int mCheckedFadeOutDuration;
Winson Chung03c568e2010-08-19 17:16:59 -070067
Michael Jurkac9a96192010-11-01 11:52:08 -070068 // Highlight colors
Winson Chung64a3cd42010-09-17 16:47:33 -070069 private int mHoloBlurColor;
70 private int mHoloOutlineColor;
Winson Chung64a3cd42010-09-17 16:47:33 -070071
Michael Jurka8245a862011-02-01 17:53:59 -080072 HolographicPagedViewIcon mHolographicOutlineView;
73
Michael Jurka0620bec2010-10-25 17:50:09 -070074 private static final HandlerThread sWorkerThread = new HandlerThread("pagedviewicon-helper");
75 static {
76 sWorkerThread.start();
77 }
78
79 private static final int MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE = 1;
80
81 private static final Handler sWorker = new Handler(sWorkerThread.getLooper()) {
82 private DeferredHandler mHandler = new DeferredHandler();
83 private Paint mPaint = new Paint();
84 public void handleMessage(Message msg) {
85 final PagedViewIcon icon = (PagedViewIcon) msg.obj;
86
87 final Bitmap holographicOutline = Bitmap.createBitmap(
88 icon.mIcon.getWidth(), icon.mIcon.getHeight(), Bitmap.Config.ARGB_8888);
89 Canvas holographicOutlineCanvas = new Canvas(holographicOutline);
90 holographicOutlineCanvas.drawBitmap(icon.mIcon, 0, 0, mPaint);
91
Adam Cohen5bb50bd2010-12-03 11:39:55 -080092 sHolographicOutlineHelper.applyThickExpensiveOutlineWithBlur(holographicOutline,
Michael Jurka0620bec2010-10-25 17:50:09 -070093 holographicOutlineCanvas, icon.mHoloBlurColor, icon.mHoloOutlineColor);
94
95 mHandler.post(new Runnable() {
96 public void run() {
97 icon.mHolographicOutline = holographicOutline;
98 icon.mIconCache.addOutline(icon.mIconCacheKey, holographicOutline);
Michael Jurka8245a862011-02-01 17:53:59 -080099 icon.getHolographicOutlineView().invalidate();
Michael Jurka0620bec2010-10-25 17:50:09 -0700100 }
101 });
102 }
103 };
Winson Chung64a3cd42010-09-17 16:47:33 -0700104
Winson Chungb3347bb2010-08-19 14:51:28 -0700105 public PagedViewIcon(Context context) {
106 this(context, null);
107 }
108
109 public PagedViewIcon(Context context, AttributeSet attrs) {
110 this(context, attrs, 0);
111 }
112
113 public PagedViewIcon(Context context, AttributeSet attrs, int defStyle) {
114 super(context, attrs, defStyle);
Winson Chung29d6fea2010-12-01 15:47:31 -0800115
Winson Chung64a3cd42010-09-17 16:47:33 -0700116 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedViewIcon, defStyle, 0);
117 mHoloBlurColor = a.getColor(R.styleable.PagedViewIcon_blurColor, 0);
118 mHoloOutlineColor = a.getColor(R.styleable.PagedViewIcon_outlineColor, 0);
Winson Chung64a3cd42010-09-17 16:47:33 -0700119 a.recycle();
Winson Chungb3347bb2010-08-19 14:51:28 -0700120
121 if (sHolographicOutlineHelper == null) {
Winson Chung64a3cd42010-09-17 16:47:33 -0700122 sHolographicOutlineHelper = new HolographicOutlineHelper();
Winson Chungb3347bb2010-08-19 14:51:28 -0700123 }
Winson Chungb3347bb2010-08-19 14:51:28 -0700124
Winson Chung59e1f9a2010-12-21 11:31:54 -0800125 // Set up fade in/out constants
126 final Resources r = context.getResources();
Winson Chung785d2eb2011-04-14 16:08:02 -0700127 final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha);
Winson Chung59e1f9a2010-12-21 11:31:54 -0800128 if (alpha > 0) {
Winson Chung785d2eb2011-04-14 16:08:02 -0700129 mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f;
130 mCheckedFadeInDuration =
131 r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration);
132 mCheckedFadeOutDuration =
133 r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration);
Winson Chung59e1f9a2010-12-21 11:31:54 -0800134 }
135
Michael Jurka8245a862011-02-01 17:53:59 -0800136 mHolographicOutlineView = new HolographicPagedViewIcon(context, this);
Winson Chungb46a2d12011-04-22 14:13:05 -0700137 mHolographicEffectsEnabled = isHardwareAccelerated();
Michael Jurka8245a862011-02-01 17:53:59 -0800138 }
139
140 protected HolographicPagedViewIcon getHolographicOutlineView() {
141 return mHolographicOutlineView;
142 }
143
144 protected Bitmap getHolographicOutline() {
145 return mHolographicOutline;
Winson Chungb3347bb2010-08-19 14:51:28 -0700146 }
147
Winson Chung823c9692011-03-01 10:57:29 -0800148 private boolean queueHolographicOutlineCreation() {
Michael Jurka0620bec2010-10-25 17:50:09 -0700149 // Generate the outline in the background
150 if (mHolographicOutline == null) {
151 Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE);
152 m.obj = this;
153 sWorker.sendMessage(m);
Winson Chung823c9692011-03-01 10:57:29 -0800154 return true;
Michael Jurka0620bec2010-10-25 17:50:09 -0700155 }
Winson Chung823c9692011-03-01 10:57:29 -0800156 return false;
Michael Jurka0620bec2010-10-25 17:50:09 -0700157 }
158
Winson Chungdf4b83d2010-10-20 17:49:27 -0700159 public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache,
Winson Chung04998342011-01-05 13:54:43 -0800160 boolean scaleUp, boolean createHolographicOutlines) {
Michael Jurkac9a96192010-11-01 11:52:08 -0700161 mIcon = info.iconBitmap;
Michael Jurka0620bec2010-10-25 17:50:09 -0700162 setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
Winson Chung241c3b42010-08-25 16:53:03 -0700163 setText(info.title);
164 setTag(info);
Michael Jurka0620bec2010-10-25 17:50:09 -0700165
Winson Chung04998342011-01-05 13:54:43 -0800166 if (createHolographicOutlines) {
167 mIconCache = cache;
168 mIconCacheKey = new PagedViewIconCache.Key(info);
169 mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
Winson Chungb46a2d12011-04-22 14:13:05 -0700170 if (mHolographicEffectsEnabled && !queueHolographicOutlineCreation()) {
Winson Chung823c9692011-03-01 10:57:29 -0800171 getHolographicOutlineView().invalidate();
172 }
Winson Chung04998342011-01-05 13:54:43 -0800173 }
Winson Chung241c3b42010-08-25 16:53:03 -0700174 }
175
176 public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager,
Winson Chung04998342011-01-05 13:54:43 -0800177 PagedViewIconCache cache, IconCache modelIconCache, boolean createHolographicOutlines) {
Winson Chung4dbea792011-05-05 14:21:32 -0700178 ComponentName cn = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
179 mIcon = modelIconCache.getIcon(cn, info);
Michael Jurka0620bec2010-10-25 17:50:09 -0700180 setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
Winson Chung241c3b42010-08-25 16:53:03 -0700181 setText(info.loadLabel(packageManager));
182 setTag(info);
Michael Jurka0620bec2010-10-25 17:50:09 -0700183
Winson Chung04998342011-01-05 13:54:43 -0800184 if (createHolographicOutlines) {
185 mIconCache = cache;
186 mIconCacheKey = new PagedViewIconCache.Key(info);
187 mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
Winson Chungb46a2d12011-04-22 14:13:05 -0700188 if (mHolographicEffectsEnabled && !queueHolographicOutlineCreation()) {
Winson Chung823c9692011-03-01 10:57:29 -0800189 getHolographicOutlineView().invalidate();
190 }
Winson Chung04998342011-01-05 13:54:43 -0800191 }
Winson Chung241c3b42010-08-25 16:53:03 -0700192 }
193
Winson Chungb3347bb2010-08-19 14:51:28 -0700194 @Override
195 public void setAlpha(float alpha) {
196 final float viewAlpha = sHolographicOutlineHelper.viewAlphaInterpolator(alpha);
Winson Chungb3347bb2010-08-19 14:51:28 -0700197 final float holographicAlpha = sHolographicOutlineHelper.highlightAlphaInterpolator(alpha);
Winson Chunge22a8e92010-11-12 13:40:58 -0800198 int newViewAlpha = (int) (viewAlpha * 255);
199 int newHolographicAlpha = (int) (holographicAlpha * 255);
200 if ((mAlpha != newViewAlpha) || (mHolographicAlpha != newHolographicAlpha)) {
201 mAlpha = newViewAlpha;
202 mHolographicAlpha = newHolographicAlpha;
203 super.setAlpha(viewAlpha);
204 }
Winson Chungb3347bb2010-08-19 14:51:28 -0700205 }
206
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700207 public void invalidateCheckedImage() {
208 if (mCheckedOutline != null) {
209 mCheckedOutline.recycle();
210 mCheckedOutline = null;
211 }
212 }
213
Winson Chungb3347bb2010-08-19 14:51:28 -0700214 @Override
Michael Jurka0620bec2010-10-25 17:50:09 -0700215 protected void onDraw(Canvas canvas) {
216 if (mAlpha > 0) {
217 super.onDraw(canvas);
218 }
Winson Chungb3347bb2010-08-19 14:51:28 -0700219
Michael Jurka0620bec2010-10-25 17:50:09 -0700220 Bitmap overlay = null;
Winson Chungb3347bb2010-08-19 14:51:28 -0700221
Michael Jurka0620bec2010-10-25 17:50:09 -0700222 // draw any blended overlays
223 if (mCheckedOutline == null) {
Winson Chungb46a2d12011-04-22 14:13:05 -0700224 if (mHolographicEffectsEnabled && mHolographicOutline != null
225 && mHolographicAlpha > 0) {
Michael Jurka0620bec2010-10-25 17:50:09 -0700226 mPaint.setAlpha(mHolographicAlpha);
227 overlay = mHolographicOutline;
228 }
229 } else {
230 mPaint.setAlpha(255);
231 overlay = mCheckedOutline;
232 }
233
234 if (overlay != null) {
Winson Chungc84001e2010-11-09 12:20:57 -0800235 final int offset = getScrollX();
Michael Jurka0620bec2010-10-25 17:50:09 -0700236 final int compoundPaddingLeft = getCompoundPaddingLeft();
237 final int compoundPaddingRight = getCompoundPaddingRight();
238 int hspace = getWidth() - compoundPaddingRight - compoundPaddingLeft;
239 canvas.drawBitmap(overlay,
Winson Chungc84001e2010-11-09 12:20:57 -0800240 offset + compoundPaddingLeft + (hspace - overlay.getWidth()) / 2,
Michael Jurka0620bec2010-10-25 17:50:09 -0700241 mPaddingTop,
242 mPaint);
Winson Chungb3347bb2010-08-19 14:51:28 -0700243 }
244 }
245
Winson Chungb3347bb2010-08-19 14:51:28 -0700246 @Override
Michael Jurka0620bec2010-10-25 17:50:09 -0700247 public void onDetachedFromWindow() {
248 super.onDetachedFromWindow();
249 sWorker.removeMessages(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE, this);
Winson Chungb3347bb2010-08-19 14:51:28 -0700250 }
Winson Chung03c568e2010-08-19 17:16:59 -0700251
252 @Override
Winson Chung97d85d22011-04-13 11:27:36 -0700253 public boolean onKeyDown(int keyCode, KeyEvent event) {
254 return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
255 || super.onKeyDown(keyCode, event);
256 }
257
258 @Override
259 public boolean onKeyUp(int keyCode, KeyEvent event) {
260 return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
261 || super.onKeyUp(keyCode, event);
262 }
263
264 @Override
Winson Chung03c568e2010-08-19 17:16:59 -0700265 public boolean isChecked() {
266 return mIsChecked;
267 }
268
Patrick Dubroy5f445422011-02-18 14:35:21 -0800269 void setChecked(boolean checked, boolean animate) {
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700270 if (mIsChecked != checked) {
271 mIsChecked = checked;
272
Winson Chungcd4bc492010-12-09 18:52:32 -0800273 float alpha;
274 int duration;
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700275 if (mIsChecked) {
Winson Chung59e1f9a2010-12-21 11:31:54 -0800276 alpha = mCheckedAlpha;
277 duration = mCheckedFadeInDuration;
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700278 } else {
Winson Chungcd4bc492010-12-09 18:52:32 -0800279 alpha = 1.0f;
Winson Chung59e1f9a2010-12-21 11:31:54 -0800280 duration = mCheckedFadeOutDuration;
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700281 }
282
Winson Chungcd4bc492010-12-09 18:52:32 -0800283 // Initialize the animator
284 if (mCheckedAlphaAnimator != null) {
285 mCheckedAlphaAnimator.cancel();
286 }
Patrick Dubroy5f445422011-02-18 14:35:21 -0800287 if (animate) {
288 mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha);
289 mCheckedAlphaAnimator.setDuration(duration);
290 mCheckedAlphaAnimator.start();
291 } else {
292 setAlpha(alpha);
293 }
Winson Chungcd4bc492010-12-09 18:52:32 -0800294
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700295 invalidate();
296 }
Winson Chung03c568e2010-08-19 17:16:59 -0700297 }
298
299 @Override
Patrick Dubroy5f445422011-02-18 14:35:21 -0800300 public void setChecked(boolean checked) {
301 setChecked(checked, true);
302 }
303
304 @Override
Winson Chung03c568e2010-08-19 17:16:59 -0700305 public void toggle() {
306 setChecked(!mIsChecked);
307 }
Winson Chungb3347bb2010-08-19 14:51:28 -0700308}