blob: f1b8a01d04eeca95f026a2f93b51b7afc8060d4a [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 Chungb3347bb2010-08-19 14:51:28 -070022import android.content.Context;
Winson Chung241c3b42010-08-25 16:53:03 -070023import android.content.pm.PackageManager;
24import android.content.pm.ResolveInfo;
Winson Chung59e1f9a2010-12-21 11:31:54 -080025import android.content.res.Resources;
Winson Chung64a3cd42010-09-17 16:47:33 -070026import android.content.res.TypedArray;
Winson Chungb3347bb2010-08-19 14:51:28 -070027import android.graphics.Bitmap;
Winson Chungb3347bb2010-08-19 14:51:28 -070028import android.graphics.Canvas;
Winson Chungb3347bb2010-08-19 14:51:28 -070029import android.graphics.Paint;
Michael Jurka0620bec2010-10-25 17:50:09 -070030import android.os.Handler;
31import android.os.HandlerThread;
32import android.os.Message;
Winson Chungb3347bb2010-08-19 14:51:28 -070033import android.util.AttributeSet;
Winson Chung97d85d22011-04-13 11:27:36 -070034import android.view.KeyEvent;
Winson Chung03c568e2010-08-19 17:16:59 -070035import android.widget.Checkable;
Michael Jurka742574b2011-02-02 23:51:01 -080036import android.widget.TextView;
Winson Chungc84001e2010-11-09 12:20:57 -080037
Winson Chung241c3b42010-08-25 16:53:03 -070038
Winson Chungb3347bb2010-08-19 14:51:28 -070039
40/**
41 * An icon on a PagedView, specifically for items in the launcher's paged view (with compound
42 * drawables on the top).
43 */
Michael Jurkac0759f52011-02-03 16:47:14 -080044public class PagedViewIcon extends CachedTextView implements Checkable {
Winson Chungb3347bb2010-08-19 14:51:28 -070045 private static final String TAG = "PagedViewIcon";
46
47 // holographic outline
48 private final Paint mPaint = new Paint();
49 private static HolographicOutlineHelper sHolographicOutlineHelper;
Winson Chung5f2aa4e2010-08-20 14:49:25 -070050 private Bitmap mCheckedOutline;
Winson Chungb3347bb2010-08-19 14:51:28 -070051 private Bitmap mHolographicOutline;
Michael Jurka0620bec2010-10-25 17:50:09 -070052 private Bitmap mIcon;
Winson Chungb3347bb2010-08-19 14:51:28 -070053
Winson Chung04998342011-01-05 13:54:43 -080054 private PagedViewIconCache.Key mIconCacheKey;
Winson Chung241c3b42010-08-25 16:53:03 -070055 private PagedViewIconCache mIconCache;
56
Winson Chung88127032010-12-13 12:11:33 -080057 private int mAlpha = 255;
Winson Chungb3347bb2010-08-19 14:51:28 -070058 private int mHolographicAlpha;
59
Winson Chung03c568e2010-08-19 17:16:59 -070060 private boolean mIsChecked;
Winson Chungcd4bc492010-12-09 18:52:32 -080061 private ObjectAnimator mCheckedAlphaAnimator;
Winson Chung59e1f9a2010-12-21 11:31:54 -080062 private float mCheckedAlpha = 1.0f;
63 private int mCheckedFadeInDuration;
64 private int mCheckedFadeOutDuration;
Winson Chung03c568e2010-08-19 17:16:59 -070065
Michael Jurkac9a96192010-11-01 11:52:08 -070066 // Highlight colors
Winson Chung64a3cd42010-09-17 16:47:33 -070067 private int mHoloBlurColor;
68 private int mHoloOutlineColor;
Winson Chung64a3cd42010-09-17 16:47:33 -070069
Michael Jurka8245a862011-02-01 17:53:59 -080070 HolographicPagedViewIcon mHolographicOutlineView;
71
Michael Jurka0620bec2010-10-25 17:50:09 -070072 private static final HandlerThread sWorkerThread = new HandlerThread("pagedviewicon-helper");
73 static {
74 sWorkerThread.start();
75 }
76
77 private static final int MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE = 1;
78
79 private static final Handler sWorker = new Handler(sWorkerThread.getLooper()) {
80 private DeferredHandler mHandler = new DeferredHandler();
81 private Paint mPaint = new Paint();
82 public void handleMessage(Message msg) {
83 final PagedViewIcon icon = (PagedViewIcon) msg.obj;
84
85 final Bitmap holographicOutline = Bitmap.createBitmap(
86 icon.mIcon.getWidth(), icon.mIcon.getHeight(), Bitmap.Config.ARGB_8888);
87 Canvas holographicOutlineCanvas = new Canvas(holographicOutline);
88 holographicOutlineCanvas.drawBitmap(icon.mIcon, 0, 0, mPaint);
89
Adam Cohen5bb50bd2010-12-03 11:39:55 -080090 sHolographicOutlineHelper.applyThickExpensiveOutlineWithBlur(holographicOutline,
Michael Jurka0620bec2010-10-25 17:50:09 -070091 holographicOutlineCanvas, icon.mHoloBlurColor, icon.mHoloOutlineColor);
92
93 mHandler.post(new Runnable() {
94 public void run() {
95 icon.mHolographicOutline = holographicOutline;
96 icon.mIconCache.addOutline(icon.mIconCacheKey, holographicOutline);
Michael Jurka8245a862011-02-01 17:53:59 -080097 icon.getHolographicOutlineView().invalidate();
Michael Jurka0620bec2010-10-25 17:50:09 -070098 }
99 });
100 }
101 };
Winson Chung64a3cd42010-09-17 16:47:33 -0700102
Winson Chungb3347bb2010-08-19 14:51:28 -0700103 public PagedViewIcon(Context context) {
104 this(context, null);
105 }
106
107 public PagedViewIcon(Context context, AttributeSet attrs) {
108 this(context, attrs, 0);
109 }
110
111 public PagedViewIcon(Context context, AttributeSet attrs, int defStyle) {
112 super(context, attrs, defStyle);
Winson Chung29d6fea2010-12-01 15:47:31 -0800113
Winson Chung64a3cd42010-09-17 16:47:33 -0700114 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedViewIcon, defStyle, 0);
115 mHoloBlurColor = a.getColor(R.styleable.PagedViewIcon_blurColor, 0);
116 mHoloOutlineColor = a.getColor(R.styleable.PagedViewIcon_outlineColor, 0);
Winson Chung64a3cd42010-09-17 16:47:33 -0700117 a.recycle();
Winson Chungb3347bb2010-08-19 14:51:28 -0700118
119 if (sHolographicOutlineHelper == null) {
Winson Chung64a3cd42010-09-17 16:47:33 -0700120 sHolographicOutlineHelper = new HolographicOutlineHelper();
Winson Chungb3347bb2010-08-19 14:51:28 -0700121 }
Winson Chungb3347bb2010-08-19 14:51:28 -0700122
Winson Chung59e1f9a2010-12-21 11:31:54 -0800123 // Set up fade in/out constants
124 final Resources r = context.getResources();
Winson Chung785d2eb2011-04-14 16:08:02 -0700125 final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha);
Winson Chung59e1f9a2010-12-21 11:31:54 -0800126 if (alpha > 0) {
Winson Chung785d2eb2011-04-14 16:08:02 -0700127 mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f;
128 mCheckedFadeInDuration =
129 r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration);
130 mCheckedFadeOutDuration =
131 r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration);
Winson Chung59e1f9a2010-12-21 11:31:54 -0800132 }
133
Michael Jurka8245a862011-02-01 17:53:59 -0800134 mHolographicOutlineView = new HolographicPagedViewIcon(context, this);
135 }
136
137 protected HolographicPagedViewIcon getHolographicOutlineView() {
138 return mHolographicOutlineView;
139 }
140
141 protected Bitmap getHolographicOutline() {
142 return mHolographicOutline;
Winson Chungb3347bb2010-08-19 14:51:28 -0700143 }
144
Winson Chung823c9692011-03-01 10:57:29 -0800145 private boolean queueHolographicOutlineCreation() {
Michael Jurka0620bec2010-10-25 17:50:09 -0700146 // Generate the outline in the background
147 if (mHolographicOutline == null) {
148 Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE);
149 m.obj = this;
150 sWorker.sendMessage(m);
Winson Chung823c9692011-03-01 10:57:29 -0800151 return true;
Michael Jurka0620bec2010-10-25 17:50:09 -0700152 }
Winson Chung823c9692011-03-01 10:57:29 -0800153 return false;
Michael Jurka0620bec2010-10-25 17:50:09 -0700154 }
155
Winson Chungdf4b83d2010-10-20 17:49:27 -0700156 public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache,
Winson Chung04998342011-01-05 13:54:43 -0800157 boolean scaleUp, boolean createHolographicOutlines) {
Michael Jurkac9a96192010-11-01 11:52:08 -0700158 mIcon = info.iconBitmap;
Michael Jurka0620bec2010-10-25 17:50:09 -0700159 setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
Winson Chung241c3b42010-08-25 16:53:03 -0700160 setText(info.title);
161 setTag(info);
Michael Jurka0620bec2010-10-25 17:50:09 -0700162
Winson Chung04998342011-01-05 13:54:43 -0800163 if (createHolographicOutlines) {
164 mIconCache = cache;
165 mIconCacheKey = new PagedViewIconCache.Key(info);
166 mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
Winson Chung823c9692011-03-01 10:57:29 -0800167 if (!queueHolographicOutlineCreation()) {
168 getHolographicOutlineView().invalidate();
169 }
Winson Chung04998342011-01-05 13:54:43 -0800170 }
Winson Chung241c3b42010-08-25 16:53:03 -0700171 }
172
173 public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager,
Winson Chung04998342011-01-05 13:54:43 -0800174 PagedViewIconCache cache, IconCache modelIconCache, boolean createHolographicOutlines) {
Michael Jurkac9a96192010-11-01 11:52:08 -0700175 mIcon = Utilities.createIconBitmap(
176 modelIconCache.getFullResIcon(info, packageManager), mContext);
Michael Jurka0620bec2010-10-25 17:50:09 -0700177 setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
Winson Chung241c3b42010-08-25 16:53:03 -0700178 setText(info.loadLabel(packageManager));
179 setTag(info);
Michael Jurka0620bec2010-10-25 17:50:09 -0700180
Winson Chung04998342011-01-05 13:54:43 -0800181 if (createHolographicOutlines) {
182 mIconCache = cache;
183 mIconCacheKey = new PagedViewIconCache.Key(info);
184 mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
Winson Chung823c9692011-03-01 10:57:29 -0800185 if (!queueHolographicOutlineCreation()) {
186 getHolographicOutlineView().invalidate();
187 }
Winson Chung04998342011-01-05 13:54:43 -0800188 }
Winson Chung241c3b42010-08-25 16:53:03 -0700189 }
190
Winson Chungb3347bb2010-08-19 14:51:28 -0700191 @Override
192 public void setAlpha(float alpha) {
193 final float viewAlpha = sHolographicOutlineHelper.viewAlphaInterpolator(alpha);
Winson Chungb3347bb2010-08-19 14:51:28 -0700194 final float holographicAlpha = sHolographicOutlineHelper.highlightAlphaInterpolator(alpha);
Winson Chunge22a8e92010-11-12 13:40:58 -0800195 int newViewAlpha = (int) (viewAlpha * 255);
196 int newHolographicAlpha = (int) (holographicAlpha * 255);
197 if ((mAlpha != newViewAlpha) || (mHolographicAlpha != newHolographicAlpha)) {
198 mAlpha = newViewAlpha;
199 mHolographicAlpha = newHolographicAlpha;
200 super.setAlpha(viewAlpha);
201 }
Winson Chungb3347bb2010-08-19 14:51:28 -0700202 }
203
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700204 public void invalidateCheckedImage() {
205 if (mCheckedOutline != null) {
206 mCheckedOutline.recycle();
207 mCheckedOutline = null;
208 }
209 }
210
Winson Chungb3347bb2010-08-19 14:51:28 -0700211 @Override
Michael Jurka0620bec2010-10-25 17:50:09 -0700212 protected void onDraw(Canvas canvas) {
213 if (mAlpha > 0) {
214 super.onDraw(canvas);
215 }
Winson Chungb3347bb2010-08-19 14:51:28 -0700216
Michael Jurka0620bec2010-10-25 17:50:09 -0700217 Bitmap overlay = null;
Winson Chungb3347bb2010-08-19 14:51:28 -0700218
Michael Jurka0620bec2010-10-25 17:50:09 -0700219 // draw any blended overlays
220 if (mCheckedOutline == null) {
221 if (mHolographicOutline != null && mHolographicAlpha > 0) {
222 mPaint.setAlpha(mHolographicAlpha);
223 overlay = mHolographicOutline;
224 }
225 } else {
226 mPaint.setAlpha(255);
227 overlay = mCheckedOutline;
228 }
229
230 if (overlay != null) {
Winson Chungc84001e2010-11-09 12:20:57 -0800231 final int offset = getScrollX();
Michael Jurka0620bec2010-10-25 17:50:09 -0700232 final int compoundPaddingLeft = getCompoundPaddingLeft();
233 final int compoundPaddingRight = getCompoundPaddingRight();
234 int hspace = getWidth() - compoundPaddingRight - compoundPaddingLeft;
235 canvas.drawBitmap(overlay,
Winson Chungc84001e2010-11-09 12:20:57 -0800236 offset + compoundPaddingLeft + (hspace - overlay.getWidth()) / 2,
Michael Jurka0620bec2010-10-25 17:50:09 -0700237 mPaddingTop,
238 mPaint);
Winson Chungb3347bb2010-08-19 14:51:28 -0700239 }
240 }
241
Winson Chungb3347bb2010-08-19 14:51:28 -0700242 @Override
Michael Jurka0620bec2010-10-25 17:50:09 -0700243 public void onDetachedFromWindow() {
244 super.onDetachedFromWindow();
245 sWorker.removeMessages(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE, this);
Winson Chungb3347bb2010-08-19 14:51:28 -0700246 }
Winson Chung03c568e2010-08-19 17:16:59 -0700247
248 @Override
Winson Chung97d85d22011-04-13 11:27:36 -0700249 public boolean onKeyDown(int keyCode, KeyEvent event) {
250 return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
251 || super.onKeyDown(keyCode, event);
252 }
253
254 @Override
255 public boolean onKeyUp(int keyCode, KeyEvent event) {
256 return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
257 || super.onKeyUp(keyCode, event);
258 }
259
260 @Override
Winson Chung03c568e2010-08-19 17:16:59 -0700261 public boolean isChecked() {
262 return mIsChecked;
263 }
264
Patrick Dubroy5f445422011-02-18 14:35:21 -0800265 void setChecked(boolean checked, boolean animate) {
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700266 if (mIsChecked != checked) {
267 mIsChecked = checked;
268
Winson Chungcd4bc492010-12-09 18:52:32 -0800269 float alpha;
270 int duration;
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700271 if (mIsChecked) {
Winson Chung59e1f9a2010-12-21 11:31:54 -0800272 alpha = mCheckedAlpha;
273 duration = mCheckedFadeInDuration;
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700274 } else {
Winson Chungcd4bc492010-12-09 18:52:32 -0800275 alpha = 1.0f;
Winson Chung59e1f9a2010-12-21 11:31:54 -0800276 duration = mCheckedFadeOutDuration;
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700277 }
278
Winson Chungcd4bc492010-12-09 18:52:32 -0800279 // Initialize the animator
280 if (mCheckedAlphaAnimator != null) {
281 mCheckedAlphaAnimator.cancel();
282 }
Patrick Dubroy5f445422011-02-18 14:35:21 -0800283 if (animate) {
284 mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha);
285 mCheckedAlphaAnimator.setDuration(duration);
286 mCheckedAlphaAnimator.start();
287 } else {
288 setAlpha(alpha);
289 }
Winson Chungcd4bc492010-12-09 18:52:32 -0800290
Winson Chung5f2aa4e2010-08-20 14:49:25 -0700291 invalidate();
292 }
Winson Chung03c568e2010-08-19 17:16:59 -0700293 }
294
295 @Override
Patrick Dubroy5f445422011-02-18 14:35:21 -0800296 public void setChecked(boolean checked) {
297 setChecked(checked, true);
298 }
299
300 @Override
Winson Chung03c568e2010-08-19 17:16:59 -0700301 public void toggle() {
302 setChecked(!mIsChecked);
303 }
Winson Chungb3347bb2010-08-19 14:51:28 -0700304}