blob: 010271f3e04abe771a444d6474391d1ce17c9d29 [file] [log] [blame]
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001/*
2 * Copyright (C) 2008 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
Joe Onoratoa5902522009-07-30 13:37:37 -070017package com.android.launcher2;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080018
Adam Cohen2801caf2011-05-13 20:57:39 -070019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
Adam Cohen2801caf2011-05-13 20:57:39 -070021import android.animation.ValueAnimator;
22import android.animation.ValueAnimator.AnimatorUpdateListener;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080023import android.content.Context;
24import android.content.res.Resources;
Adam Cohena9cf38f2011-05-02 15:36:58 -070025import android.graphics.Canvas;
Adam Cohenf4b08912011-05-17 18:45:47 -070026import android.graphics.Color;
Adam Cohenbadf71e2011-05-26 19:08:29 -070027import android.graphics.PorterDuff;
Adam Cohen3e8f8112011-07-02 18:03:00 -070028import android.graphics.Rect;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080029import android.graphics.drawable.Drawable;
30import android.util.AttributeSet;
31import android.view.LayoutInflater;
Adam Cohen7c693212011-05-18 15:26:57 -070032import android.view.View;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080033import android.view.ViewGroup;
Adam Cohen3e8f8112011-07-02 18:03:00 -070034import android.view.animation.AccelerateInterpolator;
35import android.view.animation.DecelerateInterpolator;
Adam Cohen76fc0852011-06-17 13:26:23 -070036import android.widget.ImageView;
37import android.widget.LinearLayout;
Adam Cohena9cf38f2011-05-02 15:36:58 -070038import android.widget.TextView;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080039
Romain Guyedcce092010-03-04 13:03:17 -080040import com.android.launcher.R;
Adam Cohenc0dcf592011-06-01 15:30:43 -070041import com.android.launcher2.DropTarget.DragObject;
Adam Cohena9cf38f2011-05-02 15:36:58 -070042import com.android.launcher2.FolderInfo.FolderListener;
Romain Guyedcce092010-03-04 13:03:17 -080043
Adam Cohenc0dcf592011-06-01 15:30:43 -070044import java.util.ArrayList;
45
The Android Open Source Project31dd5032009-03-03 19:32:27 -080046/**
47 * An icon that can appear on in the workspace representing an {@link UserFolder}.
48 */
Adam Cohen76fc0852011-06-17 13:26:23 -070049public class FolderIcon extends LinearLayout implements FolderListener {
The Android Open Source Project31dd5032009-03-03 19:32:27 -080050 private Launcher mLauncher;
Adam Cohena9cf38f2011-05-02 15:36:58 -070051 Folder mFolder;
52 FolderInfo mInfo;
53
Adam Cohenbadf71e2011-05-26 19:08:29 -070054 // The number of icons to display in the
Adam Cohen76fc0852011-06-17 13:26:23 -070055 private static final int NUM_ITEMS_IN_PREVIEW = 3;
Adam Cohenf4b08912011-05-17 18:45:47 -070056 private static final int CONSUMPTION_ANIMATION_DURATION = 100;
Adam Cohenbadf71e2011-05-26 19:08:29 -070057
58 // The degree to which the inner ring grows when accepting drop
Adam Cohen69ce2e52011-07-03 19:25:21 -070059 private static final float INNER_RING_GROWTH_FACTOR = 0.15f;
Adam Cohenbadf71e2011-05-26 19:08:29 -070060
Adam Cohenbadf71e2011-05-26 19:08:29 -070061 // The degree to which the outer ring is scaled in its natural state
Adam Cohen69ce2e52011-07-03 19:25:21 -070062 private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
Adam Cohenbadf71e2011-05-26 19:08:29 -070063
64 // The amount of vertical spread between items in the stack [0...1]
Adam Cohen76fc0852011-06-17 13:26:23 -070065 private static final float PERSPECTIVE_SHIFT_FACTOR = 0.24f;
Adam Cohenbadf71e2011-05-26 19:08:29 -070066
67 // The degree to which the item in the back of the stack is scaled [0...1]
68 // (0 means it's not scaled at all, 1 means it's scaled to nothing)
Adam Cohen76fc0852011-06-17 13:26:23 -070069 private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f;
Adam Cohenbadf71e2011-05-26 19:08:29 -070070
Adam Cohen073a46f2011-05-17 16:28:09 -070071 private int mOriginalWidth = -1;
72 private int mOriginalHeight = -1;
Adam Cohen76fc0852011-06-17 13:26:23 -070073 private ImageView mPreviewBackground;
74 private BubbleTextView mFolderName;
Adam Cohen073a46f2011-05-17 16:28:09 -070075
Adam Cohen19072da2011-05-31 14:30:45 -070076 FolderRingAnimator mFolderRingAnimator = null;
Adam Cohen2801caf2011-05-13 20:57:39 -070077
The Android Open Source Project31dd5032009-03-03 19:32:27 -080078 public FolderIcon(Context context, AttributeSet attrs) {
79 super(context, attrs);
80 }
81
82 public FolderIcon(Context context) {
83 super(context);
84 }
85
Michael Jurka0280c3b2010-09-17 15:00:07 -070086 public boolean isDropEnabled() {
Winson Chung7a1d1652011-03-18 15:56:01 -070087 final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
88 final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
89 final Workspace workspace = (Workspace) cellLayout.getParent();
90 return !workspace.isSmall();
Michael Jurka0280c3b2010-09-17 15:00:07 -070091 }
92
The Android Open Source Project31dd5032009-03-03 19:32:27 -080093 static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
Adam Cohendf2cc412011-04-27 16:56:57 -070094 FolderInfo folderInfo, IconCache iconCache) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -080095
96 FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
97
Adam Cohen76fc0852011-06-17 13:26:23 -070098 icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_name);
99 icon.mFolderName.setText(folderInfo.title);
100 icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background);
Winson Chung6a0f57d2011-06-29 20:10:49 -0700101 icon.mPreviewBackground.setContentDescription(folderInfo.title);
Adam Cohen76fc0852011-06-17 13:26:23 -0700102
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800103 icon.setTag(folderInfo);
104 icon.setOnClickListener(launcher);
105 icon.mInfo = folderInfo;
106 icon.mLauncher = launcher;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700107
108 Folder folder = Folder.fromXml(launcher);
109 folder.setDragController(launcher.getDragController());
110 folder.setLauncher(launcher);
Adam Cohen2801caf2011-05-13 20:57:39 -0700111 folder.setFolderIcon(icon);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700112 folder.bind(folderInfo);
113 icon.mFolder = folder;
Adam Cohen19072da2011-05-31 14:30:45 -0700114 icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon);
Adam Cohen69ce2e52011-07-03 19:25:21 -0700115
Adam Cohena9cf38f2011-05-02 15:36:58 -0700116 folderInfo.addListener(icon);
Adam Cohen19072da2011-05-31 14:30:45 -0700117
118 return icon;
119 }
120
121 public static class FolderRingAnimator {
Adam Cohen69ce2e52011-07-03 19:25:21 -0700122 public int mCellX;
123 public int mCellY;
124 private CellLayout mCellLayout;
Adam Cohen76fc0852011-06-17 13:26:23 -0700125 public float mOuterRingSize;
126 public float mInnerRingSize;
Adam Cohen19072da2011-05-31 14:30:45 -0700127 public FolderIcon mFolderIcon = null;
Adam Cohenc0dcf592011-06-01 15:30:43 -0700128 public Drawable mOuterRingDrawable = null;
129 public Drawable mInnerRingDrawable = null;
130 public static Drawable sSharedOuterRingDrawable = null;
131 public static Drawable sSharedInnerRingDrawable = null;
Adam Cohen76fc0852011-06-17 13:26:23 -0700132 public static int sPreviewSize = -1;
133 public static int sPreviewPadding = -1;
134
Adam Cohenc0dcf592011-06-01 15:30:43 -0700135 private ValueAnimator mAcceptAnimator;
136 private ValueAnimator mNeutralAnimator;
Adam Cohen19072da2011-05-31 14:30:45 -0700137
138 public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) {
Adam Cohen19072da2011-05-31 14:30:45 -0700139 mFolderIcon = folderIcon;
Adam Cohen76fc0852011-06-17 13:26:23 -0700140 Resources res = launcher.getResources();
141 mOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo);
142 mInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_holo);
143
144 if (sPreviewSize < 0 || sPreviewPadding < 0) {
145 sPreviewSize = res.getDimensionPixelSize(R.dimen.folder_preview_size);
146 sPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding);
147 }
Adam Cohenc0dcf592011-06-01 15:30:43 -0700148 if (sSharedOuterRingDrawable == null) {
Adam Cohen76fc0852011-06-17 13:26:23 -0700149 sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo);
Adam Cohen19072da2011-05-31 14:30:45 -0700150 }
Adam Cohenc0dcf592011-06-01 15:30:43 -0700151 if (sSharedInnerRingDrawable == null) {
Adam Cohen76fc0852011-06-17 13:26:23 -0700152 sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_holo);
Adam Cohen19072da2011-05-31 14:30:45 -0700153 }
Adam Cohen073a46f2011-05-17 16:28:09 -0700154 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700155
Adam Cohen19072da2011-05-31 14:30:45 -0700156 public void animateToAcceptState() {
Adam Cohenc0dcf592011-06-01 15:30:43 -0700157 if (mNeutralAnimator != null) {
158 mNeutralAnimator.cancel();
159 }
160 mAcceptAnimator = ValueAnimator.ofFloat(0f, 1f);
161 mAcceptAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
162 mAcceptAnimator.addUpdateListener(new AnimatorUpdateListener() {
Adam Cohen19072da2011-05-31 14:30:45 -0700163 public void onAnimationUpdate(ValueAnimator animation) {
164 final float percent = (Float) animation.getAnimatedValue();
Adam Cohen76fc0852011-06-17 13:26:23 -0700165 mOuterRingSize = (1 + percent * OUTER_RING_GROWTH_FACTOR) * sPreviewSize;
166 mInnerRingSize = (1 + percent * INNER_RING_GROWTH_FACTOR) * sPreviewSize;
Adam Cohen69ce2e52011-07-03 19:25:21 -0700167 if (mCellLayout != null) {
168 mCellLayout.invalidate();
Adam Cohen19072da2011-05-31 14:30:45 -0700169 }
170 }
171 });
Adam Cohenc0dcf592011-06-01 15:30:43 -0700172 mAcceptAnimator.addListener(new AnimatorListenerAdapter() {
Adam Cohen19072da2011-05-31 14:30:45 -0700173 @Override
Adam Cohenc0dcf592011-06-01 15:30:43 -0700174 public void onAnimationStart(Animator animation) {
Adam Cohen19072da2011-05-31 14:30:45 -0700175 if (mFolderIcon != null) {
Adam Cohen76fc0852011-06-17 13:26:23 -0700176 mFolderIcon.mPreviewBackground.setVisibility(INVISIBLE);
Adam Cohen19072da2011-05-31 14:30:45 -0700177 }
178 }
179 });
Adam Cohenc0dcf592011-06-01 15:30:43 -0700180 mAcceptAnimator.start();
Adam Cohen19072da2011-05-31 14:30:45 -0700181 }
182
183 public void animateToNaturalState() {
Adam Cohenc0dcf592011-06-01 15:30:43 -0700184 if (mAcceptAnimator != null) {
185 mAcceptAnimator.cancel();
186 }
187 mNeutralAnimator = ValueAnimator.ofFloat(0f, 1f);
188 mNeutralAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
189 mNeutralAnimator.addUpdateListener(new AnimatorUpdateListener() {
Adam Cohen19072da2011-05-31 14:30:45 -0700190 public void onAnimationUpdate(ValueAnimator animation) {
191 final float percent = (Float) animation.getAnimatedValue();
Adam Cohen76fc0852011-06-17 13:26:23 -0700192 mOuterRingSize = (1 + (1 - percent) * OUTER_RING_GROWTH_FACTOR) * sPreviewSize;
193 mInnerRingSize = (1 + (1 - percent) * INNER_RING_GROWTH_FACTOR) * sPreviewSize;
Adam Cohen69ce2e52011-07-03 19:25:21 -0700194 if (mCellLayout != null) {
195 mCellLayout.invalidate();
Adam Cohen19072da2011-05-31 14:30:45 -0700196 }
197 }
198 });
Adam Cohenc0dcf592011-06-01 15:30:43 -0700199 mNeutralAnimator.addListener(new AnimatorListenerAdapter() {
Adam Cohen19072da2011-05-31 14:30:45 -0700200 @Override
201 public void onAnimationEnd(Animator animation) {
Adam Cohen69ce2e52011-07-03 19:25:21 -0700202 if (mCellLayout != null) {
203 mCellLayout.hideFolderAccept(FolderRingAnimator.this);
204 }
Adam Cohen19072da2011-05-31 14:30:45 -0700205 if (mFolderIcon != null) {
Adam Cohen76fc0852011-06-17 13:26:23 -0700206 mFolderIcon.mPreviewBackground.setVisibility(VISIBLE);
Adam Cohen19072da2011-05-31 14:30:45 -0700207 }
Adam Cohen19072da2011-05-31 14:30:45 -0700208 }
209 });
Adam Cohenc0dcf592011-06-01 15:30:43 -0700210 mNeutralAnimator.start();
Adam Cohen19072da2011-05-31 14:30:45 -0700211 }
212
Adam Cohenc0dcf592011-06-01 15:30:43 -0700213 // Location is expressed in window coordinates
Adam Cohen69ce2e52011-07-03 19:25:21 -0700214 public void getCell(int[] loc) {
215 loc[0] = mCellX;
216 loc[1] = mCellY;
217 }
218
219 // Location is expressed in window coordinates
220 public void setCell(int x, int y) {
221 mCellX = x;
222 mCellY = y;
223 }
224
225 public void setCellLayout(CellLayout layout) {
226 mCellLayout = layout;
Adam Cohen19072da2011-05-31 14:30:45 -0700227 }
228
Adam Cohen76fc0852011-06-17 13:26:23 -0700229 public float getOuterRingSize() {
230 return mOuterRingSize;
Adam Cohen19072da2011-05-31 14:30:45 -0700231 }
232
Adam Cohen76fc0852011-06-17 13:26:23 -0700233 public float getInnerRingSize() {
234 return mInnerRingSize;
Adam Cohen19072da2011-05-31 14:30:45 -0700235 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800236 }
237
Adam Cohen073a46f2011-05-17 16:28:09 -0700238 private boolean willAcceptItem(ItemInfo item) {
239 final int itemType = item.itemType;
240 return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
241 itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
242 !mFolder.isFull() && item != mInfo);
243 }
244
Adam Cohenc0dcf592011-06-01 15:30:43 -0700245 public boolean acceptDrop(Object dragInfo) {
246 final ItemInfo item = (ItemInfo) dragInfo;
Adam Cohen073a46f2011-05-17 16:28:09 -0700247 return willAcceptItem(item);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800248 }
249
Adam Cohendf035382011-04-11 17:22:04 -0700250 public void addItem(ShortcutInfo item) {
251 mInfo.add(item);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700252 LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
Adam Cohendf035382011-04-11 17:22:04 -0700253 }
254
Adam Cohen2801caf2011-05-13 20:57:39 -0700255 void saveState(CellLayout.LayoutParams lp) {
256 mOriginalWidth = lp.width;
257 mOriginalHeight = lp.height;
Adam Cohen2801caf2011-05-13 20:57:39 -0700258 }
259
Adam Cohenc0dcf592011-06-01 15:30:43 -0700260 public void onDragEnter(Object dragInfo) {
261 if (!willAcceptItem((ItemInfo) dragInfo)) return;
Adam Cohen69ce2e52011-07-03 19:25:21 -0700262 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
263 CellLayout layout = (CellLayout) getParent().getParent();
264 mFolderRingAnimator.setCell(lp.cellX, lp.cellY);
265 mFolderRingAnimator.setCellLayout(layout);
Adam Cohen19072da2011-05-31 14:30:45 -0700266 mFolderRingAnimator.animateToAcceptState();
Adam Cohen69ce2e52011-07-03 19:25:21 -0700267 layout.showFolderAccept(mFolderRingAnimator);
Adam Cohen073a46f2011-05-17 16:28:09 -0700268 }
269
Adam Cohenc0dcf592011-06-01 15:30:43 -0700270 public void onDragOver(Object dragInfo) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800271 }
272
Adam Cohenc0dcf592011-06-01 15:30:43 -0700273 public void onDragExit(Object dragInfo) {
274 if (!willAcceptItem((ItemInfo) dragInfo)) return;
Adam Cohen19072da2011-05-31 14:30:45 -0700275 mFolderRingAnimator.animateToNaturalState();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800276 }
Patrick Dubroy440c3602010-07-13 17:50:32 -0700277
Adam Cohen3e8f8112011-07-02 18:03:00 -0700278 public void onDrop(DragObject d) {
Adam Cohenc0dcf592011-06-01 15:30:43 -0700279 ShortcutInfo item;
Adam Cohen3e8f8112011-07-02 18:03:00 -0700280 if (d.dragInfo instanceof ApplicationInfo) {
Adam Cohenc0dcf592011-06-01 15:30:43 -0700281 // Came from all apps -- make a copy
Adam Cohen3e8f8112011-07-02 18:03:00 -0700282 item = ((ApplicationInfo) d.dragInfo).makeShortcut();
Adam Cohenc0dcf592011-06-01 15:30:43 -0700283 } else {
Adam Cohen3e8f8112011-07-02 18:03:00 -0700284 item = (ShortcutInfo) d.dragInfo;
Adam Cohenc0dcf592011-06-01 15:30:43 -0700285 }
286 item.cellX = -1;
287 item.cellY = -1;
288 addItem(item);
Adam Cohen3e8f8112011-07-02 18:03:00 -0700289 DragLayer dragLayer = mLauncher.getDragLayer();
290 Rect from = new Rect();
291 dragLayer.getViewRectRelativeToSelf(d.dragView, from);
292 Rect to = new Rect();
293 dragLayer.getDescendantRectRelativeToSelf(this, to);
294
295 int previewSize = FolderRingAnimator.sPreviewSize;
296 int vanishingPointX = (int) (previewSize * 0.7);
297 int vanishingPointY = (int) (previewSize * (1 - 0.88f));
298 to.offset(vanishingPointX - previewSize / 2 , vanishingPointY - previewSize / 2);
299
300 dragLayer.animateView(d.dragView, from, to, 0f, 0.2f, 400, new DecelerateInterpolator(2),
301 new AccelerateInterpolator(2));
Adam Cohenc0dcf592011-06-01 15:30:43 -0700302 }
303
Adam Cohencb3382b2011-05-24 14:07:08 -0700304 public DropTarget getDropTargetDelegate(DragObject d) {
Patrick Dubroy440c3602010-07-13 17:50:32 -0700305 return null;
306 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700307
308 @Override
Adam Cohenc0dcf592011-06-01 15:30:43 -0700309 protected void dispatchDraw(Canvas canvas) {
Adam Cohen76fc0852011-06-17 13:26:23 -0700310 super.dispatchDraw(canvas);
311
Adam Cohena9cf38f2011-05-02 15:36:58 -0700312 if (mFolder == null) return;
313 if (mFolder.getItemCount() == 0) return;
314
315 canvas.save();
316 TextView v = (TextView) mFolder.getItemAt(0);
317 Drawable d = v.getCompoundDrawables()[1];
Adam Cohen76fc0852011-06-17 13:26:23 -0700318 int intrinsicIconSize = d.getIntrinsicHeight();
Adam Cohena9cf38f2011-05-02 15:36:58 -0700319
Adam Cohen073a46f2011-05-17 16:28:09 -0700320 if (mOriginalWidth < 0 || mOriginalHeight < 0) {
321 mOriginalWidth = getMeasuredWidth();
322 mOriginalHeight = getMeasuredHeight();
323 }
Adam Cohen76fc0852011-06-17 13:26:23 -0700324 final int previewSize = FolderRingAnimator.sPreviewSize;
325 final int previewPadding = FolderRingAnimator.sPreviewPadding;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700326
Adam Cohen76fc0852011-06-17 13:26:23 -0700327 int halfAvailableSpace = (previewSize - 2 * previewPadding) / 2;
328 // cos(45) = 0.707 + ~= 0.1)
329 int availableSpace = (int) (halfAvailableSpace * (1 + 0.8f));
Adam Cohenbadf71e2011-05-26 19:08:29 -0700330
Adam Cohen76fc0852011-06-17 13:26:23 -0700331 int unscaledHeight = (int) (intrinsicIconSize * (1 + PERSPECTIVE_SHIFT_FACTOR));
332 float baselineIconScale = (1.0f * availableSpace / unscaledHeight);
333
334 int baselineSize = (int) (intrinsicIconSize * baselineIconScale);
335 float maxPerspectiveShift = baselineSize * PERSPECTIVE_SHIFT_FACTOR;
Adam Cohena9cf38f2011-05-02 15:36:58 -0700336
Adam Cohen76078c42011-06-09 15:06:52 -0700337 ArrayList<View> items = mFolder.getItemsInReadingOrder(false);
Adam Cohenbadf71e2011-05-26 19:08:29 -0700338
Adam Cohen76fc0852011-06-17 13:26:23 -0700339 int xShift = (mOriginalWidth - 2 * halfAvailableSpace) / 2;
Adam Cohen69ce2e52011-07-03 19:25:21 -0700340 int yShift = previewPadding + getPaddingTop();
Adam Cohenbadf71e2011-05-26 19:08:29 -0700341 canvas.translate(xShift, yShift);
Adam Cohen3e8f8112011-07-02 18:03:00 -0700342 int nItemsInPreview = Math.min(items.size(), NUM_ITEMS_IN_PREVIEW);
343 for (int i = nItemsInPreview - 1; i >= 0; i--) {
344 int index = NUM_ITEMS_IN_PREVIEW - i - 1;
Adam Cohenbadf71e2011-05-26 19:08:29 -0700345
346 float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1);
347 float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r));
Adam Cohenbadf71e2011-05-26 19:08:29 -0700348
Adam Cohen76fc0852011-06-17 13:26:23 -0700349 float offset = (1 - r) * maxPerspectiveShift;
350 float scaledSize = scale * baselineSize;
351 float scaleOffsetCorrection = (1 - scale) * baselineSize;
352
353 // We want to imagine our coordinates from the bottom left, growing up and to the
354 // right. This is natural for the x-axis, but for the y-axis, we have to invert things.
355 float transY = 2 * halfAvailableSpace - (offset + scaledSize + scaleOffsetCorrection);
356 float transX = offset + scaleOffsetCorrection;
Adam Cohenbadf71e2011-05-26 19:08:29 -0700357
Adam Cohen7c693212011-05-18 15:26:57 -0700358 v = (TextView) items.get(i);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700359 d = v.getCompoundDrawables()[1];
360
Adam Cohenbadf71e2011-05-26 19:08:29 -0700361 canvas.save();
362 canvas.translate(transX, transY);
363 canvas.scale(baselineIconScale * scale, baselineIconScale * scale);
Adam Cohenf4b08912011-05-17 18:45:47 -0700364
Adam Cohenbadf71e2011-05-26 19:08:29 -0700365 int overlayAlpha = (int) (80 * (1 - r));
Adam Cohena9cf38f2011-05-02 15:36:58 -0700366 if (d != null) {
Adam Cohen76fc0852011-06-17 13:26:23 -0700367 d.setBounds(0, 0, intrinsicIconSize, intrinsicIconSize);
368 d.setFilterBitmap(true);
Adam Cohenbadf71e2011-05-26 19:08:29 -0700369 d.setColorFilter(Color.argb(overlayAlpha, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700370 d.draw(canvas);
Adam Cohenbadf71e2011-05-26 19:08:29 -0700371 d.clearColorFilter();
Adam Cohen76fc0852011-06-17 13:26:23 -0700372 d.setFilterBitmap(false);
Adam Cohena9cf38f2011-05-02 15:36:58 -0700373 }
Adam Cohenbadf71e2011-05-26 19:08:29 -0700374 canvas.restore();
Adam Cohena9cf38f2011-05-02 15:36:58 -0700375 }
Adam Cohena9cf38f2011-05-02 15:36:58 -0700376 canvas.restore();
377 }
378
Adam Cohen76078c42011-06-09 15:06:52 -0700379 public void onItemsChanged() {
380 invalidate();
381 requestLayout();
382 }
383
Adam Cohena9cf38f2011-05-02 15:36:58 -0700384 public void onAdd(ShortcutInfo item) {
385 invalidate();
386 requestLayout();
387 }
388
389 public void onRemove(ShortcutInfo item) {
390 invalidate();
391 requestLayout();
392 }
Adam Cohen76fc0852011-06-17 13:26:23 -0700393
394 public void onTitleChanged(CharSequence title) {
Adam Cohend63cfa92011-06-24 14:17:17 -0700395 mFolderName.setText(title.toString());
Winson Chung6a0f57d2011-06-29 20:10:49 -0700396 mPreviewBackground.setContentDescription(title.toString());
Adam Cohen76fc0852011-06-17 13:26:23 -0700397 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800398}