PagedViewIcon.java revision 67b2f6cba5aa7b5d0fac5e66ba8f3d5f887baee6
1/*
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
19import android.content.Context;
20import android.content.pm.PackageManager;
21import android.content.pm.ResolveInfo;
22import android.content.res.TypedArray;
23import android.graphics.Bitmap;
24import android.graphics.Canvas;
25import android.graphics.Paint;
26import android.os.Handler;
27import android.os.HandlerThread;
28import android.os.Message;
29import android.util.AttributeSet;
30import android.widget.Checkable;
31import android.widget.TextView;
32
33import com.android.launcher.R;
34import com.android.launcher2.PagedView.PagedViewIconCache;
35
36
37
38/**
39 * An icon on a PagedView, specifically for items in the launcher's paged view (with compound
40 * drawables on the top).
41 */
42public class PagedViewIcon extends CacheableTextView implements Checkable {
43    private static final String TAG = "PagedViewIcon";
44
45    // holographic outline
46    private final Paint mPaint = new Paint();
47    private static HolographicOutlineHelper sHolographicOutlineHelper;
48    private Bitmap mCheckedOutline;
49    private Bitmap mHolographicOutline;
50    private Bitmap mIcon;
51
52    private Object mIconCacheKey;
53    private PagedViewIconCache mIconCache;
54
55    private int mAlpha = -1;
56    private int mHolographicAlpha;
57
58    private boolean mIsChecked;
59
60    // Highlight colors
61    private int mHoloBlurColor;
62    private int mHoloOutlineColor;
63    private int mCheckedBlurColor;
64    private int mCheckedOutlineColor;
65
66    private static final HandlerThread sWorkerThread = new HandlerThread("pagedviewicon-helper");
67    static {
68        sWorkerThread.start();
69    }
70
71    private static final int MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE = 1;
72
73    private static final Handler sWorker = new Handler(sWorkerThread.getLooper()) {
74        private DeferredHandler mHandler = new DeferredHandler();
75        private Paint mPaint = new Paint();
76        public void handleMessage(Message msg) {
77            final PagedViewIcon icon = (PagedViewIcon) msg.obj;
78
79            final Bitmap holographicOutline = Bitmap.createBitmap(
80                    icon.mIcon.getWidth(), icon.mIcon.getHeight(), Bitmap.Config.ARGB_8888);
81            Canvas holographicOutlineCanvas = new Canvas(holographicOutline);
82            holographicOutlineCanvas.drawBitmap(icon.mIcon, 0, 0, mPaint);
83
84            sHolographicOutlineHelper.applyExpensiveOutlineWithBlur(holographicOutline,
85                    holographicOutlineCanvas, icon.mHoloBlurColor, icon.mHoloOutlineColor);
86
87            mHandler.post(new Runnable() {
88                public void run() {
89                    icon.mHolographicOutline = holographicOutline;
90                    icon.mIconCache.addOutline(icon.mIconCacheKey, holographicOutline);
91                    icon.invalidate();
92                }
93            });
94        }
95    };
96
97    public PagedViewIcon(Context context) {
98        this(context, null);
99    }
100
101    public PagedViewIcon(Context context, AttributeSet attrs) {
102        this(context, attrs, 0);
103    }
104
105    public PagedViewIcon(Context context, AttributeSet attrs, int defStyle) {
106        super(context, attrs, defStyle);
107        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedViewIcon, defStyle, 0);
108        mHoloBlurColor = a.getColor(R.styleable.PagedViewIcon_blurColor, 0);
109        mHoloOutlineColor = a.getColor(R.styleable.PagedViewIcon_outlineColor, 0);
110        mCheckedBlurColor = a.getColor(R.styleable.PagedViewIcon_checkedBlurColor, 0);
111        mCheckedOutlineColor = a.getColor(R.styleable.PagedViewIcon_checkedOutlineColor, 0);
112
113        a.recycle();
114
115        if (sHolographicOutlineHelper == null) {
116            sHolographicOutlineHelper = new HolographicOutlineHelper();
117        }
118
119        setFocusable(true);
120        setBackgroundDrawable(null);
121    }
122
123    private void queueHolographicOutlineCreation() {
124        // Generate the outline in the background
125        if (mHolographicOutline == null) {
126            Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE);
127            m.obj = this;
128            sWorker.sendMessage(m);
129        }
130    }
131
132    public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache,
133            boolean scaleUp) {
134        mIconCache = cache;
135        mIconCacheKey = info;
136        mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
137
138        mIcon = info.iconBitmap;
139        setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
140        setText(info.title);
141        buildAndEnableCache();
142        setTag(info);
143
144        queueHolographicOutlineCreation();
145    }
146
147    public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager,
148            PagedViewIconCache cache, IconCache modelIconCache) {
149        mIconCache = cache;
150        mIconCacheKey = info;
151        mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
152
153        mIcon = Utilities.createIconBitmap(
154                modelIconCache.getFullResIcon(info, packageManager), mContext);
155        setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
156        setText(info.loadLabel(packageManager));
157        buildAndEnableCache();
158        setTag(info);
159
160        queueHolographicOutlineCreation();
161    }
162
163    @Override
164    public void setAlpha(float alpha) {
165        final float viewAlpha = sHolographicOutlineHelper.viewAlphaInterpolator(alpha);
166        final float holographicAlpha = sHolographicOutlineHelper.highlightAlphaInterpolator(alpha);
167        int newViewAlpha = (int) (viewAlpha * 255);
168        int newHolographicAlpha = (int) (holographicAlpha * 255);
169        if ((mAlpha != newViewAlpha) || (mHolographicAlpha != newHolographicAlpha)) {
170            mAlpha = newViewAlpha;
171            mHolographicAlpha = newHolographicAlpha;
172            super.setAlpha(viewAlpha);
173        }
174    }
175
176    public void invalidateCheckedImage() {
177        if (mCheckedOutline != null) {
178            mCheckedOutline.recycle();
179            mCheckedOutline = null;
180        }
181    }
182
183    @Override
184    protected void onDraw(Canvas canvas) {
185        if (mAlpha > 0) {
186            super.onDraw(canvas);
187        }
188
189        Bitmap overlay = null;
190
191        // draw any blended overlays
192        if (mCheckedOutline == null) {
193            if (mHolographicOutline != null && mHolographicAlpha > 0) {
194                mPaint.setAlpha(mHolographicAlpha);
195                overlay = mHolographicOutline;
196            }
197        } else {
198            mPaint.setAlpha(255);
199            overlay = mCheckedOutline;
200        }
201
202        if (overlay != null) {
203            final int offset = getScrollX();
204            final int compoundPaddingLeft = getCompoundPaddingLeft();
205            final int compoundPaddingRight = getCompoundPaddingRight();
206            int hspace = getWidth() - compoundPaddingRight - compoundPaddingLeft;
207            canvas.drawBitmap(overlay,
208                    offset + compoundPaddingLeft + (hspace - overlay.getWidth()) / 2,
209                    mPaddingTop,
210                    mPaint);
211        }
212    }
213
214    @Override
215    public void onDetachedFromWindow() {
216        super.onDetachedFromWindow();
217        sWorker.removeMessages(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE, this);
218    }
219
220    @Override
221    public boolean isChecked() {
222        return mIsChecked;
223    }
224
225    @Override
226    public void setChecked(boolean checked) {
227        if (mIsChecked != checked) {
228            mIsChecked = checked;
229
230            if (mIsChecked) {
231                mCheckedOutline = Bitmap.createBitmap(mIcon.getWidth(), mIcon.getHeight(),
232                        Bitmap.Config.ARGB_8888);
233                Canvas checkedOutlineCanvas = new Canvas(mCheckedOutline);
234                mPaint.setAlpha(255);
235                checkedOutlineCanvas.drawBitmap(mIcon, 0, 0, mPaint);
236
237                sHolographicOutlineHelper.applyExpensiveOutlineWithBlur(mCheckedOutline,
238                        checkedOutlineCanvas, mCheckedBlurColor, mCheckedOutlineColor);
239            } else {
240                invalidateCheckedImage();
241            }
242
243            invalidate();
244        }
245    }
246
247    @Override
248    public void toggle() {
249        setChecked(!mIsChecked);
250    }
251}
252